package cn.stylefeng.guns.modular.business.frequency.finance.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.guns.core.context.login.LoginContextHolder;
import cn.stylefeng.guns.core.exception.CustomException;
import cn.stylefeng.guns.core.exception.ServiceException;
import cn.stylefeng.guns.core.factory.PageFactory;
import cn.stylefeng.guns.core.pojo.page.AndaPageResult;
import cn.stylefeng.guns.core.pojo.page.PageResult;
import cn.stylefeng.guns.core.pojo.response.ResponseData;
import cn.stylefeng.guns.modular.business.custom.constant.PublicCommon;
import cn.stylefeng.guns.modular.business.custom.enums.*;
import cn.stylefeng.guns.modular.business.frequency.banner.config.activityMq.Producer;
import cn.stylefeng.guns.modular.business.frequency.cmcity.mapper.CmCityMapper;
import cn.stylefeng.guns.modular.business.frequency.cmlinkman.entity.CmLinkman;
import cn.stylefeng.guns.modular.business.frequency.cmlinkman.mapper.CmLinkmanMapper;
import cn.stylefeng.guns.modular.business.frequency.finance.entity.Finance;
import cn.stylefeng.guns.modular.business.frequency.finance.enums.FinanceExceptionEnum;
import cn.stylefeng.guns.modular.business.frequency.finance.mapper.FinanceMapper;
import cn.stylefeng.guns.modular.business.frequency.finance.model.param.FinanceCheckVO;
import cn.stylefeng.guns.modular.business.frequency.finance.model.param.FinanceDTO;
import cn.stylefeng.guns.modular.business.frequency.finance.model.param.FinanceParam;
import cn.stylefeng.guns.modular.business.frequency.finance.model.param.SettlementVO;
import cn.stylefeng.guns.modular.business.frequency.finance.model.result.*;
import cn.stylefeng.guns.modular.business.frequency.finance.service.FinanceService;
import cn.stylefeng.guns.modular.business.frequency.financecheck.entity.FinanceCheck;
import cn.stylefeng.guns.modular.business.frequency.financecheck.mapper.FinanceCheckMapper;
import cn.stylefeng.guns.modular.business.frequency.financecheckdetail.entity.FinanceCheckDetail;
import cn.stylefeng.guns.modular.business.frequency.financecheckdetail.mapper.FinanceCheckDetailMapper;
import cn.stylefeng.guns.modular.business.frequency.financecheckdetail.service.FinanceCheckDetailService;
import cn.stylefeng.guns.modular.business.frequency.financedetail.entity.FinanceDetail;
import cn.stylefeng.guns.modular.business.frequency.financedetail.mapper.FinanceDetailMapper;
import cn.stylefeng.guns.modular.business.frequency.financesettlement.entity.FinanceSettlement;
import cn.stylefeng.guns.modular.business.frequency.financesettlement.mapper.FinanceSettlementMapper;
import cn.stylefeng.guns.modular.business.frequency.financesettlementimage.entity.FinanceSettlementImage;
import cn.stylefeng.guns.modular.business.frequency.financesettlementimage.mapper.FinanceSettlementImageMapper;
import cn.stylefeng.guns.modular.business.frequency.financetransport.entity.FinanceTransport;
import cn.stylefeng.guns.modular.business.frequency.financetransport.mapper.FinanceTransportMapper;
import cn.stylefeng.guns.modular.business.frequency.ordercarverify.mapper.OrderCarVerifyMapper;
import cn.stylefeng.guns.modular.business.frequency.orderextrafee.entity.OrderExtraFee;
import cn.stylefeng.guns.modular.business.frequency.orderextrafee.mapper.OrderExtraFeeMapper;
import cn.stylefeng.guns.modular.business.frequency.orderfinish.entity.OrderFinish;
import cn.stylefeng.guns.modular.business.frequency.orderfinish.mapper.OrderFinishMapper;
import cn.stylefeng.guns.modular.business.frequency.orderfinish.model.param.OrderFinishRecordVO;
import cn.stylefeng.guns.modular.business.frequency.orderfinish.model.param.OrderSubDelayVO;
import cn.stylefeng.guns.modular.business.frequency.orderfinish.model.param.PkgFinanceGross;
import cn.stylefeng.guns.modular.business.frequency.orderfinish.service.OrderFinishService;
import cn.stylefeng.guns.modular.business.frequency.orderfinishimage.entity.OrderFinishImage;
import cn.stylefeng.guns.modular.business.frequency.orderfinishimage.mapper.OrderFinishImageMapper;
import cn.stylefeng.guns.modular.business.frequency.orderfinishrecord.entity.OrderFinishRecord;
import cn.stylefeng.guns.modular.business.frequency.orderfinishrecord.mapper.OrderFinishRecordMapper;
import cn.stylefeng.guns.modular.business.frequency.orderfinishrecorddetail.entity.OrderFinishRecordDetail;
import cn.stylefeng.guns.modular.business.frequency.orderfinishrecorddetail.mapper.OrderFinishRecordDetailMapper;
import cn.stylefeng.guns.modular.business.frequency.ordermodifydetail.entity.OrderModifyDetail;
import cn.stylefeng.guns.modular.business.frequency.ordermodifydetail.mapper.OrderModifyDetailMapper;
import cn.stylefeng.guns.modular.business.frequency.orderpayrecord.mapper.OrderPayRecordMapper;
import cn.stylefeng.guns.modular.business.frequency.orderroyalty.entity.OrderRoyalty;
import cn.stylefeng.guns.modular.business.frequency.orderroyalty.mapper.OrderRoyaltyMapper;
import cn.stylefeng.guns.modular.business.frequency.orderstatuschange.service.OrderStatusChangeService;
import cn.stylefeng.guns.modular.business.frequency.ordersub.entity.OrderSub;
import cn.stylefeng.guns.modular.business.frequency.ordersub.mapper.OrderSubMapper;
import cn.stylefeng.guns.modular.business.frequency.ordersub.model.result.PkgOnlinePayRecord;
import cn.stylefeng.guns.modular.business.frequency.ordersub.model.result.PkgOrderFinishRecord;
import cn.stylefeng.guns.modular.business.frequency.ordersub.model.result.PkgTransportLevelDetailSimple;
import cn.stylefeng.guns.modular.business.frequency.ordertransportrelation.entity.OrderTransportRelation;
import cn.stylefeng.guns.modular.business.frequency.ordertransportrelation.mapper.OrderTransportRelationMapper;
import cn.stylefeng.guns.modular.business.frequency.syssite.entity.SysSite;
import cn.stylefeng.guns.modular.business.frequency.syssite.service.SysSiteService;
import cn.stylefeng.guns.modular.business.frequency.transport.mapper.TransportMapper;
import cn.stylefeng.guns.modular.business.frequency.transportlevel.mapper.TransportLevelMapper;
import cn.stylefeng.guns.modular.business.frequency.transportleveldetail.entity.TransportLevelDetail;
import cn.stylefeng.guns.modular.business.frequency.transportleveldetail.mapper.TransportLevelDetailMapper;
import cn.stylefeng.guns.modular.business.timer.delay.DelayQueueManager;
import cn.stylefeng.guns.modular.business.util.BusinessUtil;
import cn.stylefeng.guns.modular.business.util.poi.ExcelFormat;
import cn.stylefeng.guns.modular.business.util.poi.ExcelUtils;
import cn.stylefeng.guns.modular.util.BaseUtils;
import cn.stylefeng.guns.sys.modular.util.SnowIdUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 订单财务信息表 服务实现类
 *
 * @author yujie
 * @date 2023/05/09 17:17
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> implements FinanceService {
    @Resource
    private Producer producer;
    @Resource
    private OrderStatusChangeService orderStatusChangeService;
    @Resource
    private OrderFinishRecordMapper orderFinishRecordMapper;
    @Autowired
    private OrderFinishService finishService;
    @Resource
    private OrderFinishRecordDetailMapper orderFinishRecordDetailMapper;
    @Resource
    private OrderFinishImageMapper orderFinishImageMapper;
    @Resource
    private FinanceMapper financeMapper;
    @Resource
    private OrderFinishMapper orderFinishMapper;
    @Resource
    private OrderTransportRelationMapper orderTransportRelationMapper;
    @Resource
    private TransportLevelDetailMapper transportLevelDetailMapper;
    @Resource
    private TransportMapper transportMapper;
    @Resource
    private TransportLevelMapper transportLevelMapper;
    @Resource
    private CmLinkmanMapper linkmanMapper;
    @Resource
    private OrderModifyDetailMapper orderModifyDetailMapper;

    @Resource
    private OrderPayRecordMapper orderPayRecordMapper;
    @Resource
    private OrderCarVerifyMapper orderCarVerifyMapper;
    @Resource
    private DelayQueueManager delayQueueManager;


    @Autowired
    private OrderRoyaltyMapper orderRoyaltyMapper;
    @Autowired
    private OrderSubMapper orderSubMapper;
    @Autowired
    private OrderExtraFeeMapper orderExtraFeeMapper;
    @Autowired
    private FinanceTransportMapper financeTransportMapper;
    @Resource
    private CmCityMapper cmCityMapper;
    @Resource
    private FinanceDetailMapper financeDetailMapper;
    @Resource
    private FinanceSettlementMapper financeSettlementMapper;
    @Resource
    private FinanceSettlementImageMapper financeSettlementImageMapper;
    @Resource
    private FinanceCheckMapper financeCheckMapper;
    @Resource
    private FinanceCheckDetailMapper financeCheckDetailMapper;
    @Autowired
    private FinanceCheckDetailService financeCheckDetailService;
    @Autowired
    private SysSiteService siteService;

    @Autowired
    private BusinessUtil businessUtil;


    @Override
    public PageResult<Finance> page(FinanceParam financeParam) {

        // 构造条件
        LambdaQueryWrapper<Finance> queryWrapper = new LambdaQueryWrapper<>();

        // 查询分页结果
        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }

    @Override
    public List<Finance> list(FinanceParam financeParam) {

        // 构造条件
        LambdaQueryWrapper<Finance> queryWrapper = new LambdaQueryWrapper<>();

        return this.list(queryWrapper);
    }

    @Override
    public void add(FinanceParam financeParam) {

        // 将dto转为实体
        Finance finance = new Finance();
        BeanUtil.copyProperties(financeParam, finance);

        this.save(finance);
    }

    @Override
    public void delete(FinanceParam financeParam) {
        this.removeById(financeParam.getId());
    }

    @Override
    public void edit(FinanceParam financeParam) {

        // 根据id查询实体
        Finance finance = this.queryFinance(financeParam);

        // 请求参数转化为实体
        BeanUtil.copyProperties(financeParam, finance);

        this.updateById(finance);
    }

    @Override
    public Finance detail(FinanceParam financeParam) {
        return this.queryFinance(financeParam);
    }

    @Override
    public void changeFinanceStatus(Long orderId) {
        PkgFinance pkgFinance = this.baseMapper.getPkgFinanceByOrderId(orderId);
        if (pkgFinance != null) {
            // collectionStatus
            if (pkgFinance.getTotalUnCollection() != null && pkgFinance.getTotalUnCollection().compareTo(BigDecimal.ZERO) == 0) {
                this.baseMapper.updateCollectionStatus(2, orderId);
                // 应收收完更改奖金、提成状态
                //orderBonusMapper.updateStatusByOrderId(2, orderId);
                orderRoyaltyMapper.updateStatusByOrderId(2, orderId);
            } else {
                this.baseMapper.updateCollectionStatus(0, orderId);
            }
            // paymentStatus
            // 订单状态已完成
            int orderStatus = orderSubMapper.getStatusById(orderId);
            boolean totalHasPay = false;
            boolean transportHasPay = false;
            boolean otherHasPay = false;
            if (pkgFinance.getTotalUnPayment().compareTo(BigDecimal.ZERO) == 0) {
                totalHasPay = true;
            }
            // 未付承运费
            BigDecimal unPayTransportFee = financeTransportMapper.getUnPayTransportFeeByOrderId(orderId);
            if (unPayTransportFee.compareTo(BigDecimal.ZERO) == 0) {
                transportHasPay = true;
            }
            // 未付其他费用
            BigDecimal unPayOtherFee = orderExtraFeeMapper.getUnPayOtherFeeByOrderId(orderId);
            if (unPayOtherFee.compareTo(BigDecimal.ZERO) == 0) {
                otherHasPay = true;
            }
            // 订单完成是前提
            if (orderStatus == OrderStatusEnum.CUSTOMER_HAS_SIGN.status) {
                if (totalHasPay && transportHasPay && otherHasPay) {
                    this.baseMapper.updatePaymentStatus(2, orderId);
                }
            }
            if (!totalHasPay || !transportHasPay || !otherHasPay) {
                this.baseMapper.updatePaymentStatus(0, orderId);
            }
        }

    }


    @Override
    public void changeFinanceStatus2(Long orderId) {
        PkgFinance pkgFinance = this.baseMapper.getPkgFinanceByOrderId(orderId);
        if (pkgFinance != null) {
            // collectionStatus
            if (pkgFinance.getTotalUnCollection() != null && pkgFinance.getTotalUnCollection().compareTo(BigDecimal.ZERO) == 0) {
                this.baseMapper.updateCollectionStatus(2, orderId);
                // 应收收完更改奖金、提成状态
                //orderBonusMapper.updateStatusByOrderId(2, orderId);
                orderRoyaltyMapper.updateStatusByOrderId(2, orderId);
            } else {
                this.baseMapper.updateCollectionStatus(0, orderId);
            }
            // paymentStatus
            // 订单状态已完成
            int orderStatus = orderSubMapper.getStatusById(orderId);
            boolean totalHasPay = false;
            boolean transportHasPay = false;
            boolean otherHasPay = false;
            if (pkgFinance.getTotalUnPayment().compareTo(BigDecimal.ZERO) == 0) {
                totalHasPay = true;
            }
            // 未付承运费
            BigDecimal unPayTransportFee = financeTransportMapper.getUnPayTransportFeeByOrderId(orderId);
            if (unPayTransportFee.compareTo(BigDecimal.ZERO) == 0) {
                transportHasPay = true;
            }
            // 未付其他费用
            BigDecimal unPayOtherFee = orderExtraFeeMapper.getUnPayOtherFeeByOrderId(orderId);
            if (unPayOtherFee.compareTo(BigDecimal.ZERO) == 0) {
                otherHasPay = true;
            }
            // 订单完成是前提
            if (orderStatus == OrderStatusEnum.CUSTOMER_HAS_SIGN.status) {
                if (totalHasPay && transportHasPay && otherHasPay) {
                    this.baseMapper.updatePaymentStatus(2, orderId);
                }
            }
            if (!totalHasPay || !transportHasPay || !otherHasPay) {
                this.baseMapper.updatePaymentStatus(0, orderId);
            }
        }

    }

    @Override
    public ResponseData getCollectionList(Page<Object> defaultPage, FinanceDTO financeDTO) {
        AndaPageResult<Object> result = new AndaPageResult<>();
        Page<PkgFinanceCollection> list = financeMapper.getCollectionList(defaultPage, financeDTO, businessUtil.getTenantId());

        //查询已收的所有订单的渠道
        List<FinanceSettlementChannelResult> financeSettlementChannel = financeMapper.getFinanceSettlementChannel(LoginContextHolder.me().getTenantId());
        Map<String, String> financeSettlementChannelResultMap = new HashMap<>();
        financeSettlementChannel.stream().forEach(x -> {
            financeSettlementChannelResultMap.put(x.getOrderId(), x.getChannel());
        });

        list.getRecords().stream().forEach(x -> {
            x.setChannel("－");
            String s = financeSettlementChannelResultMap.get(x.getOrderId());
            if (StringUtils.isNotBlank(s)) {
                String replace = s.replace("5", "").replace(",", "").trim();
                if (replace.length() == 0) {
                    x.setChannel("汇付支付");
                }
            }
        });

        result.AndaPageResult(list, financeDTO);
        result.setSummary(financeMapper.getCollectionSummary(financeDTO, businessUtil.getTenantId()));
        return ResponseData.andaSuccess(result);
    }

    @Override
    public ResponseData getSiteCollection(Page<Object> defaultPage) {
        Page<SiteFinanceCollection> list = financeMapper.getSiteCollectionList1(defaultPage, businessUtil.getTenantId(),
                LoginContextHolder.me().isTenantAdmin() ? null : LoginContextHolder.me().getSysLoginUserId());
        SysSite site = siteService.getById(businessUtil.getSiteId());
        //进行非空校验
        if (list != null && CollectionUtil.isNotEmpty(list.getRecords()) && site != null) {
            for (SiteFinanceCollection collection : list.getRecords()) {
                collection.setSiteName(site.getName());
            }
        }
        return ResponseData.andaSuccess(list);
    }

    @Override
    public ResponseData sitePayment() {
        Page<SiteFinanceCollection> page = this.baseMapper.sitePayment(PageFactory.defaultPage(), LoginContextHolder.me().isTenantAdmin() ? null : LoginContextHolder.me().getSysLoginUserId(), businessUtil.getTenantId());
        if (businessUtil.getSiteId() != null) {
            SysSite sysSite = siteService.getById(businessUtil.getSiteId());
            if (sysSite != null && page.getRecords().size() > 0) {
                for (SiteFinanceCollection collection : page.getRecords()) {
                    collection.setSiteName(sysSite.getName());
                }
            }
        }
        return ResponseData.success(page);
    }


    @Override
    public ResponseData getPaymentList(Page<Object> defaultPage, FinanceDTO financeDTO) {
        AndaPageResult<Object> result = new AndaPageResult<>();
        Page<PkgFinancePayment> list = financeMapper.getPaymentList(defaultPage, financeDTO, businessUtil.getTenantId());
        result.AndaPageResult(list, financeDTO);
        result.setSummary(financeMapper.getPaymentSummary(financeDTO, businessUtil.getTenantId()));
        return ResponseData.andaSuccess(result);
    }

    @Override
    public List<FinanceTransport> getPaymentTransportListByOrderId(String orderId) {
        return financeTransportMapper.getPaymentTransportListByOrderId(orderId, businessUtil.getTenantId());
    }

    @Override
    public List<OrderExtraFee> getPaymentExtraListByOrderId(String orderId) {
        return orderExtraFeeMapper.getPaymentExtraListByOrderId(orderId);
    }

    @Override
    public List<PkgFinanceCheck> getFinanceCheckList(FinanceDTO financeDTO) {
        if (financeDTO.getSettlementIdList() != null && financeDTO.getSettlementIdList().size() > 0) {
            List<String> siteAndSettlement = new ArrayList<>();
            List<String> transportList = new ArrayList<>();
            for (String id : financeDTO.getSettlementIdList()) {
                if (StringUtils.isBlank(id)) {
                    continue;
                }
                if (id.length() < 10) {
                    transportList.add(id);
                } else if (id.length() > 10) {
                    siteAndSettlement.add(id);
                }
            }
            financeDTO.setSettlementIdList(siteAndSettlement);
            transportList.addAll(financeDTO.getCheckTransportNoList());
            financeDTO.setCheckTransportNoList(transportList);
        }
        return financeMapper.getFinanceCheckList(financeDTO, businessUtil.getTenantId());
    }

    @Override
    public PkgFinanceCheck getFinanceCheckSummary(FinanceDTO financeDTO) {
        return financeMapper.getFinanceCheckSummary(financeDTO, businessUtil.getTenantId());
    }

    @Override
    public ResponseData getFinanceGrossList(Page<Object> defaultPage, FinanceDTO financeDTO) {
        AndaPageResult<Object> result = new AndaPageResult<>();
        Page<PkgFinanceGross> list = financeMapper.getFinanceGrossList(defaultPage, financeDTO, businessUtil.getTenantId());
        result.AndaPageResult(list, financeDTO);
        result.setSummary(financeMapper.getFinanceGrossSummary(financeDTO, businessUtil.getTenantId()));
        return ResponseData.andaSuccess(result);

    }

    @Override
    public boolean checkSettlement(SettlementVO settlementVO, StringBuilder errorMsg) {
        if (settlementVO == null) {
            settlementVO = new SettlementVO();
        }
        if (settlementVO.getFinanceSettlementId() != null) {
            FinanceSettlement financeSettlement = financeSettlementMapper.selectById(settlementVO.getFinanceSettlementId());
            settlementVO.setType(financeSettlement.getType());
        }
        if (settlementVO.getType() != 10 && settlementVO.getType() != 11) {
            if (settlementVO == null || settlementVO.getSettlementFee() == null) {
                errorMsg.append("结算金额不能为空");
                return false;
            }
            if (settlementVO.getSettlementTime() == null) {
                errorMsg.append("结算时间不能为空");
                return false;
            }
            if (settlementVO.getChannel() == null || settlementVO.getChannel() == 0) {
                errorMsg.append("收付款渠道不可为空");
                return false;
            }
            // 结算金额不可大于未收、未付金额
            FinanceDetail fd = financeDetailMapper.getByOrderIdAndType(settlementVO.getOrderId(), settlementVO.getType());
            if (settlementVO.getSettlementFee().compareTo(fd.getUnSettlement()) > 0) {
                errorMsg.append("结算金额不可大于未结算金额");
                return false;
            }
        }

        return true;
    }

    @Override
    public void settlement(SettlementVO settlementVO) {
        switch (settlementVO.getType()) {
            case 1:
                spotSettlement(settlementVO, 0, null);
                break;
            case 2:
                deliverySettlement(settlementVO, 0, null);
                break;
            case 3:
                backSettlement(settlementVO, 0, null);
                break;
            case 4:
                slotSettlement(settlementVO, 0, null);
                break;
            case 5:
                kickbackSettlement(settlementVO, 0, null);
                break;
            case 6:
                pickSettlement(settlementVO, 0, null);
                break;
            case 7:
                takeSettlement(settlementVO, 0, null);
                break;
        }
        // 结算状态变更
        changeFinanceStatus(settlementVO.getOrderId());

        //手动添加的需要审核
        if (settlementVO.getType() == 10 || settlementVO.getType() == 11) {
            financeSettlementMapper.updateResultById(settlementVO.getFinanceSettlementId(), settlementVO.getResult());
        }
    }

    private void kickbackSettlement(SettlementVO settlementVO, Integer origin, Long checkId) {
        Finance finance = financeMapper.selectOne(new QueryWrapper<Finance>().lambda().eq(Finance::getOrderId, settlementVO.getOrderId()));
        if (finance != null) {
            finance.setKickbackHas(finance.getKickbackHas().add(settlementVO.getSettlementFee()));
            finance.setKickbackUn(finance.getKickbackUn().subtract(settlementVO.getSettlementFee()));
            financeMapper.updateById(finance);
        }
        // 财务明细 以及 结算记录
        dealFinanceDetail(settlementVO, origin, checkId);
    }


    private void kickbackSettlement3(SettlementVO settlementVO, Integer origin, Long checkId) {
        Finance finance = financeMapper.selectOne(new QueryWrapper<Finance>().lambda().eq(Finance::getOrderId, settlementVO.getOrderId()));
        if (finance != null) {
            finance.setKickbackHas(finance.getKickbackHas().add(settlementVO.getSettlementFee()));
            finance.setKickbackUn(finance.getKickbackUn().subtract(settlementVO.getSettlementFee()));
            financeMapper.updateById(finance);
        }

    }

    private void kickbackSettlement4(SettlementVO settlementVO, Integer origin, Long checkId) {
        Finance finance = financeMapper.selectOne(new QueryWrapper<Finance>().lambda().eq(Finance::getOrderId, settlementVO.getOrderId()));
        if (finance != null) {
            finance.setKickbackHas(finance.getKickbackHas().subtract(settlementVO.getSettlementFee()));
            finance.setKickbackUn(finance.getKickbackUn().add(settlementVO.getSettlementFee()));
            financeMapper.updateById(finance);
        }

    }


    private void takeSettlement(SettlementVO settlementVO, Integer origin, Long checkId) {
        Finance finance = financeMapper.selectOne(new QueryWrapper<Finance>().lambda().eq(Finance::getOrderId, settlementVO.getOrderId()));
        if (finance != null) {
            finance.setTakeHas(finance.getTakeHas().add(settlementVO.getSettlementFee()));
            finance.setTakeUn(finance.getTakeUn().subtract(settlementVO.getSettlementFee()));
            financeMapper.updateById(finance);
        }
        // 财务明细 以及 结算记录
        dealFinanceDetail(settlementVO, origin, checkId);
    }


    private void pickSettlement(SettlementVO settlementVO, Integer origin, Long checkId) {
        Finance finance = financeMapper.selectOne(new QueryWrapper<Finance>().lambda().eq(Finance::getOrderId, settlementVO.getOrderId()));
        if (finance != null) {
            finance.setPickHas(finance.getPickHas().add(settlementVO.getSettlementFee()));
            finance.setPickUn(finance.getPickUn().subtract(settlementVO.getSettlementFee()));
            financeMapper.updateById(finance);
        }
        // 财务明细 以及 结算记录
        dealFinanceDetail(settlementVO, origin, checkId);
    }

    public void finish(Long userId, OrderFinishRecordVO orderFinishRecordVO) {
        OrderFinishRecord orderFinishRecord = new OrderFinishRecord();
        BeanUtils.copyProperties(orderFinishRecordVO, orderFinishRecord);

        orderFinishRecord.setTenantId(businessUtil.getTenantId());
        orderFinishRecordMapper.insert(orderFinishRecord);
        // 交付图片保存
        if (orderFinishRecordVO.getTakeCarImageList() != null && orderFinishRecordVO.getTakeCarImageList().size() > 0) {
            for (String url : orderFinishRecordVO.getTakeCarImageList()) {
                OrderFinishImage ofi = new OrderFinishImage();
                ofi.setFinishId(orderFinishRecord.getId());
                ofi.setTenantId(businessUtil.getTenantId());
                ofi.setUrl(url);
                ofi.setType(1);
                orderFinishImageMapper.insert(ofi);
            }
        }
        if (orderFinishRecordVO.getPaymentImageList() != null && orderFinishRecordVO.getPaymentImageList().size() > 0) {
            for (String url : orderFinishRecordVO.getPaymentImageList()) {
                OrderFinishImage ofi = new OrderFinishImage();
                ofi.setFinishId(orderFinishRecord.getId());
                ofi.setUrl(url);
                ofi.setType(2);
                ofi.setTenantId(businessUtil.getTenantId());
                orderFinishImageMapper.insert(ofi);
            }
        }
        // 交付记录订单表插入
        for (Long orderId : orderFinishRecordVO.getOrderIdList()) {
            OrderFinishRecordDetail ofrd = new OrderFinishRecordDetail();
            ofrd.setFinishRecordId(orderFinishRecord.getId());
            ofrd.setTenantId(businessUtil.getTenantId());
            ofrd.setOrderId(orderId);
            orderFinishRecordDetailMapper.insert(ofrd);
            // OrderFinish处理
            OrderFinish orderFinish = new OrderFinish();
            BeanUtils.copyProperties(orderFinishRecordVO, orderFinish);
            orderFinish.setOrderId(orderId);
            // 计算营业额，毛利数据
            PkgFinanceGross orderGross = financeMapper.getFinanceGrossByOrderId(orderId);
            orderFinish.setCollectionFee(orderGross.getTotalCollection());
            orderFinish.setPaymentFee(orderGross.getTotalPayment());
            orderFinish.setGrossFee(orderGross.getGross());
            orderFinishMapper.insert(orderFinish);
            // 转账
            if (orderFinish.getType() != null && orderFinish.getType() == 2) {
                if (orderFinishRecordVO.getPaymentImageList() != null && orderFinishRecordVO.getPaymentImageList().size() > 0) {
                    // 转账凭证
                    financeMapper.updateHasTransferVoucher(orderFinish.getOrderId());
                    System.out.println();
                }
            }
            // 子订单状态
            orderSubMapper.updateStatusById(orderFinish.getOrderId(), OrderStatusEnum.CUSTOMER_HAS_SIGN.status, OrderStatusEnum.WAIT_TAKE.status);
            orderStatusChangeService.saveOrderStatusChange(OrderStatusEnum.WAIT_TAKE.status, OrderStatusEnum.CUSTOMER_HAS_SIGN.status, orderFinish.getOrderId(), "财务对账自动交付");
            // 运单状态修改
            // 如果运单状态为运输中，切该运单下所有直交客户的订单都已完成，则运单状态变为已签收
            // 最后一段承运

            //查询最新的一条该订单运单记录
            OrderTransportRelation otr = orderTransportRelationMapper.selectOne(new QueryWrapper<OrderTransportRelation>().lambda()
                    .eq(OrderTransportRelation::getOrderId, orderFinish.getOrderId()).last("order by transport_id desc limit 1"));
            // 运单状态
            //运单除该订单外 存在网点中转 待交付运单数量
            int unDeliveryCount = transportLevelDetailMapper.countUnDeliveryCount(otr.getTransportId(), orderFinish.getOrderId());
            //运单除该订单外 存在不是网点中转 运输中 的运单数量
            int unSignedCount = transportLevelDetailMapper.countUnSignedCount(otr.getTransportId(), orderFinish.getOrderId());
            if (unDeliveryCount == 0 && unSignedCount == 0) {
                transportMapper.updateStatusById(otr.getTransportId(), TransportStatusEnum.SIGN_FINISHED.status, null);
            } else if (unDeliveryCount == 0 && unSignedCount > 0) {
                transportMapper.updateStatusById(otr.getTransportId(), TransportStatusEnum.TRANSPORTING.status, null);
            }

            // ----------2021.08.24修改--------
            TransportLevelDetail lastLevelDetail = transportLevelDetailMapper.getLastTransportLevelDetail(orderFinish.getOrderId());
            List<TransportLevelDetail> levelDetailList = transportLevelDetailMapper.selectList(new QueryWrapper<TransportLevelDetail>().lambda().eq(TransportLevelDetail::getLevelId, lastLevelDetail.getLevelId()));
            List<Long> orderIds = levelDetailList.stream().map(TransportLevelDetail::getOrderId).collect(Collectors.toList());
            List<Integer> orderStatusList = orderSubMapper.getOrderStatusByOrderIds(orderIds);
            if (BaseUtils.listIsAll(orderStatusList, OrderStatusEnum.CUSTOMER_HAS_SIGN.status)) {
                // 分段已到达状态修改
                transportLevelMapper.updateArrivedStatus(lastLevelDetail.getLevelId());
            }
            // 财务应付状态修改
            changeFinancePaymentStatus(orderId);
            // ----------2021.08.24------------

            // 司机端送车任务状态更新--已完成
            //supplierOrderMapper.updateStatusByOrderIdAndType(orderId, 2, 3);
            // activemq通知下游系统计算奖金
            producer.sendBonus(BonusTypeEnum.DELIVERY.type, orderFinish.getOrderId(), userId, null);
            // 提成表
            OrderRoyalty orderRoyalty = new OrderRoyalty();
            orderRoyalty.setOrderId(orderFinish.getOrderId());
            orderRoyalty.setGrossFee(orderGross.getGross());
            BigDecimal royaltyFee = orderGross.getGross().subtract(new BigDecimal("40")).multiply(new BigDecimal("0.5")).compareTo(BigDecimal.ZERO) > 0 ?
                    orderGross.getGross().subtract(new BigDecimal("40")).multiply(new BigDecimal("0.5")) : BigDecimal.ZERO;
            orderRoyalty.setRoyaltyFee(royaltyFee);
            orderRoyaltyMapper.update(orderRoyalty, new QueryWrapper<OrderRoyalty>().lambda().eq(OrderRoyalty::getOrderId, orderFinish.getOrderId()));
            // 交付完成，订单确认到达延时队列
            OrderSubDelayVO osdv = new OrderSubDelayVO(orderId, new Date());
            delayQueueManager.addToDelayQueue(osdv);
        }
    }

    private void changeFinancePaymentStatus(Long orderId) {
        PkgFinance pkgFinance = financeMapper.getPkgFinanceByOrderId(orderId);
        if (pkgFinance != null) {
            boolean totalHasPay = false;
            boolean transportHasPay = false;
            boolean otherHasPay = false;
            if (pkgFinance.getTotalUnPayment().compareTo(BigDecimal.ZERO) == 0) {
                totalHasPay = true;
            }
            // 未付承运费
            BigDecimal unPayTransportFee = financeTransportMapper.getUnPayTransportFeeByOrderId(orderId);
            if (unPayTransportFee.compareTo(BigDecimal.ZERO) == 0) {
                transportHasPay = true;
            }
            // 未付其他费用
            BigDecimal unPayOtherFee = orderExtraFeeMapper.getUnPayOtherFeeByOrderId(orderId);
            if (unPayOtherFee.compareTo(BigDecimal.ZERO) == 0) {
                otherHasPay = true;
            }
            // 如果订单应付款已经全部付完，则修改应付状态
            if (totalHasPay && transportHasPay && otherHasPay) {
                financeMapper.updatePaymentStatus(2, orderId);
            }
        }
    }


    public void slotSettlement(SettlementVO settlementVO, Integer origin, Long checkId) {
        Finance finance = financeMapper.selectOne(new QueryWrapper<Finance>().lambda().eq(Finance::getOrderId, settlementVO.getOrderId()));
        if (finance != null) {
            finance.setSlotHas(finance.getSlotHas().add(settlementVO.getSettlementFee()));
            finance.setSlotUn(finance.getSlotUn().subtract(settlementVO.getSettlementFee()));
            financeMapper.updateById(finance);
            // -----2022.3.23 如果收款完成，且订单状态为待交付状态，则完成交付流程
            OrderSub os = orderSubMapper.selectById(settlementVO.getOrderId());
            if (os.getStatus() == OrderStatusEnum.WAIT_TAKE.status) {
                // 已经全部收完
                BigDecimal totalUnCollect = getTotalUnCollect(finance);
                if (totalUnCollect != null && totalUnCollect.compareTo(BigDecimal.ZERO) == 0) {
                    // 执行交付流程
                    OrderFinishRecordVO ofr = new OrderFinishRecordVO();
                    List<Long> orderIdList = new ArrayList<>();
                    orderIdList.add(settlementVO.getOrderId());
                    ofr.setOrderIdList(orderIdList);
                    Long operator = LoginContextHolder.me().getSysLoginUserId();
                    // 付款凭证
                    ofr.setPaymentImageList(settlementVO.getImgList());
                    // 备注
                    ofr.setRemark("财务结算交付");
                    ofr.setConsigneeName(os.getConsigneeName());
                    ofr.setConsigneePhone(os.getConsigneePhone());
                    // 默认银行转账
                    ofr.setType(2);

                    this.finish(operator, ofr);
                }
            }
            // -----2022.3.23 END-----------------------------------------
        }
        // 财务明细 以及 结算记录
        dealFinanceDetail(settlementVO, origin, checkId);
    }


    /**
     * 计算现付、到付、欠付、月结未收合计
     *
     * @param finance
     * @return
     */
    private BigDecimal getTotalUnCollect(Finance finance) {
        BigDecimal totalUnCollect = BigDecimal.ZERO;
        if (finance == null) {
            return null;
        }
        totalUnCollect = totalUnCollect.add(finance.getSpotUn() == null ? BigDecimal.ZERO : finance.getSpotUn())
                .add(finance.getDeliveryUn() == null ? BigDecimal.ZERO : finance.getDeliveryUn())
                .add(finance.getBackUn() == null ? BigDecimal.ZERO : finance.getBackUn())
                .add(finance.getSlotUn() == null ? BigDecimal.ZERO : finance.getSlotUn());
        return totalUnCollect;
    }

    public void backSettlement(SettlementVO settlementVO, Integer origin, Long checkId) {
        Finance finance = financeMapper.selectOne(new QueryWrapper<Finance>().lambda().eq(Finance::getOrderId, settlementVO.getOrderId()));
        if (finance != null) {
            finance.setBackHas(finance.getBackHas().add(settlementVO.getSettlementFee()));
            finance.setBackUn(finance.getBackUn().subtract(settlementVO.getSettlementFee()));
            financeMapper.updateById(finance);
            // -----2022.3.23 如果收款完成，且订单状态为待交付状态，则完成交付流程
            OrderSub os = orderSubMapper.selectById(settlementVO.getOrderId());
            if (os.getStatus() == OrderStatusEnum.WAIT_TAKE.status) {
                // 已经全部收完
                BigDecimal totalUnCollect = getTotalUnCollect(finance);
                if (totalUnCollect != null && totalUnCollect.compareTo(BigDecimal.ZERO) == 0) {
                    // 执行交付流程
                    OrderFinishRecordVO ofr = new OrderFinishRecordVO();
                    List<Long> orderIdList = new ArrayList<>();
                    orderIdList.add(settlementVO.getOrderId());
                    ofr.setOrderIdList(orderIdList);
                    Long operator = LoginContextHolder.me().getSysLoginUserId();
                    // 付款凭证
                    ofr.setPaymentImageList(settlementVO.getImgList());
                    // 备注
                    ofr.setRemark("财务结算交付");
                    ofr.setConsigneeName(os.getConsigneeName());
                    ofr.setConsigneePhone(os.getConsigneePhone());
                    // 默认银行转账
                    ofr.setType(2);

                    this.finish(operator, ofr);
                }
            }
            // -----2022.3.23 END-----------------------------------------
        }
        // 财务明细 以及 结算记录
        dealFinanceDetail(settlementVO, origin, checkId);
    }


    public void deliverySettlement(SettlementVO settlementVO, Integer origin, Long checkId) {
        Finance finance = financeMapper.selectOne(new QueryWrapper<Finance>().lambda().eq(Finance::getOrderId, settlementVO.getOrderId()));
        if (finance != null) {
            finance.setDeliveryHas(finance.getDeliveryHas().add(settlementVO.getSettlementFee()));
            finance.setDeliveryUn(finance.getDeliveryUn().subtract(settlementVO.getSettlementFee()));
            financeMapper.updateById(finance);
            // -----2022.3.23 如果收款完成，且订单状态为待交付状态，则完成交付流程
            OrderSub os = orderSubMapper.selectById(settlementVO.getOrderId());
            // 排除线上支付结算的
            if (origin != 2 && os.getStatus() == OrderStatusEnum.WAIT_TAKE.status) {
                // 已经全部收完
                BigDecimal totalUnCollect = getTotalUnCollect(finance);
                if (totalUnCollect != null && totalUnCollect.compareTo(BigDecimal.ZERO) == 0) {
                    // 执行交付流程
                    OrderFinishRecordVO ofr = new OrderFinishRecordVO();
                    List<Long> orderIdList = new ArrayList<>();
                    orderIdList.add(settlementVO.getOrderId());
                    ofr.setOrderIdList(orderIdList);
                    Long operator = LoginContextHolder.me().getSysLoginUserId();
                    // 付款凭证
                    ofr.setPaymentImageList(settlementVO.getImgList());
                    // 备注
                    ofr.setRemark("财务结算交付");
                    ofr.setConsigneeName(os.getConsigneeName());
                    ofr.setConsigneePhone(os.getConsigneePhone());
                    // 默认银行转账
                    ofr.setType(2);

                    this.finish(operator, ofr);
                }
            }
            // -----2022.3.23 END-----------------------------------------
        }
        // 财务明细 以及 结算记录
        dealFinanceDetail(settlementVO, origin, checkId);
    }


    public void spotSettlement(SettlementVO settlementVO, Integer origin, Long checkId) {
        Finance finance = financeMapper.selectOne(new QueryWrapper<Finance>().lambda().eq(Finance::getOrderId, settlementVO.getOrderId()));
        if (finance != null) {
            finance.setSpotHas(finance.getSpotHas().add(settlementVO.getSettlementFee()));
            finance.setSpotUn(finance.getSpotUn().subtract(settlementVO.getSettlementFee()));
            financeMapper.updateById(finance);
            // -----2022.3.23 如果收款完成，且订单状态为待交付状态，则完成交付流程
            OrderSub os = orderSubMapper.selectById(settlementVO.getOrderId());
            if (os.getStatus() == OrderStatusEnum.WAIT_TAKE.status) {
                // 已经全部收完
                BigDecimal totalUnCollect = getTotalUnCollect(finance);
                if (totalUnCollect != null && totalUnCollect.compareTo(BigDecimal.ZERO) == 0) {
                    // 执行交付流程
                    OrderFinishRecordVO ofr = new OrderFinishRecordVO();
                    List<Long> orderIdList = new ArrayList<>();
                    orderIdList.add(settlementVO.getOrderId());
                    ofr.setOrderIdList(orderIdList);
                    Long operator = LoginContextHolder.me().getSysLoginUserId();
                    // 付款凭证
                    ofr.setPaymentImageList(settlementVO.getImgList());
                    // 备注
                    ofr.setRemark("财务结算交付");
                    ofr.setConsigneeName(os.getConsigneeName());
                    ofr.setConsigneePhone(os.getConsigneePhone());
                    // 默认银行转账
                    ofr.setType(2);

                    this.finish(operator, ofr);
                }
            }
            // -----2022.3.23 END-----------------------------------------
        }
        // 财务明细 以及 结算记录
        dealFinanceDetail(settlementVO, origin, checkId);
    }


    public void dealFinanceDetail(SettlementVO settlementVO, Integer origin, Long checkId) {
        FinanceDetail fd = financeDetailMapper.getByOrderIdAndType(settlementVO.getOrderId(), settlementVO.getType());
        if (fd != null) {
            fd.setHasSettlement(fd.getHasSettlement().add(settlementVO.getSettlementFee()));
            fd.setUnSettlement(fd.getUnSettlement().subtract(settlementVO.getSettlementFee()));
            fd.setStatus(1);
            if (fd.getUnSettlement().compareTo(BigDecimal.ZERO) == 0) {
                fd.setStatus(2);
            }
            financeDetailMapper.updateById(fd);
        }
        FinanceSettlement fs = new FinanceSettlement(
                settlementVO.getOrderId(),
                settlementVO.getTransportId(),
                null,
                settlementVO.getSettlementFee(),
                fd.getSettlementUser(),
                fd.getSettlementPhone(),
                settlementVO.getType(),
                settlementVO.getRemark(),
                origin,
                checkId,
                settlementVO.getOperatorUser(),
                settlementVO.getSettlementTime(),
                LoginContextHolder.me().getTenantId());
        fs.setChannel(settlementVO.getChannel());
        financeSettlementMapper.insert(fs);
        if (settlementVO.getImgList() != null && settlementVO.getImgList().size() > 0) {
            // 结算图片保存
            for (String url : settlementVO.getImgList()) {
                FinanceSettlementImage image = new FinanceSettlementImage();
                image.setSettlementId(fs.getId());
                image.setUrl(url);
                image.setTenantId(businessUtil.getTenantId());
                financeSettlementImageMapper.insert(image);
            }
        }
    }


    @Override
    public boolean checkTransportSettlement(TransportSettlementVO tsv, StringBuilder errorMsg) {
        return true;
    }

    @Override
    public void transportSettlement(TransportSettlementVO tsv) {
        if (tsv.getSettlementFee() != null) {
            FinanceTransport ft = financeTransportMapper.getByOrderIdAndTransportId(tsv.getOrderId(), tsv.getTransportId());
            if (ft != null) {
                ft.setTransportHas(ft.getTransportHas().add(tsv.getSettlementFee()));
                ft.setTransportUn(ft.getTransportUn().subtract(tsv.getSettlementFee()));
                financeTransportMapper.updateById(ft);
            }
            // 结算明细及结算记录
            FinanceDetail fd = financeDetailMapper.getByOrderIdAndRelationId(8, tsv.getOrderId(), tsv.getTransportId());
            if (fd != null) {
                fd.setHasSettlement(fd.getHasSettlement().add(tsv.getSettlementFee()));
                fd.setUnSettlement(fd.getUnSettlement().subtract(tsv.getSettlementFee()));
                fd.setStatus(1);
                if (fd.getUnSettlement().compareTo(BigDecimal.ZERO) == 0) {
                    fd.setStatus(2);
                }
                financeDetailMapper.updateById(fd);
            }
            FinanceSettlement fs = new FinanceSettlement(
                    tsv.getOrderId(),
                    tsv.getTransportId(),
                    null,
                    tsv.getSettlementFee(),
                    fd.getSettlementUser(),
                    fd.getSettlementPhone(),
                    8,
                    tsv.getRemark(),
                    0,
                    null,
                    LoginContextHolder.me().getSysLoginUserId(),
                    tsv.getSettlementTime(),
                    LoginContextHolder.me().getTenantId());
            fs.setChannel(tsv.getChannel());
            financeSettlementMapper.insert(fs);
            if (tsv.getImgList() != null && tsv.getImgList().size() > 0) {
                // 结算图片保存
                for (String url : tsv.getImgList()) {
                    FinanceSettlementImage image = new FinanceSettlementImage();
                    image.setSettlementId(fs.getId());
                    image.setUrl(url);
                    financeSettlementImageMapper.insert(image);
                }
            }
        }
        // 结算状态变更
        changeFinanceStatus(tsv.getOrderId());
    }

    @Override
    public boolean checkExtraSettlement(TransportSettlementVO transportSettlementVO, StringBuilder errorMsg) {
        return true;
    }

    @Override
    public void extraSettlement(TransportSettlementVO tsv) {
        if (tsv.getSettlementFee() != null) {
            OrderExtraFee oef = orderExtraFeeMapper.selectById(tsv.getId());
            if (oef != null) {
                oef.setHasSettlement(oef.getHasSettlement().add(tsv.getSettlementFee()));
                oef.setUnSettlement(oef.getUnSettlement().subtract(tsv.getSettlementFee()));
                orderExtraFeeMapper.updateById(oef);
            }
            // 结算明细及结算记录
            FinanceDetail fd = financeDetailMapper.getByOrderIdAndRelationId(9, tsv.getOrderId(), tsv.getId());
            if (fd != null) {
                fd.setHasSettlement(fd.getHasSettlement().add(tsv.getSettlementFee()));
                fd.setUnSettlement(fd.getUnSettlement().subtract(tsv.getSettlementFee()));
                fd.setStatus(1);
                if (fd.getUnSettlement().compareTo(BigDecimal.ZERO) == 0) {
                    fd.setStatus(2);
                }
                financeDetailMapper.updateById(fd);
            }
            FinanceSettlement fs = new FinanceSettlement(

                    tsv.getOrderId(),
                    tsv.getTransportId(),
                    oef.getId(),
                    tsv.getSettlementFee(),
                    fd.getSettlementUser(),
                    fd.getSettlementPhone(),
                    9,
                    tsv.getRemark(),
                    0,
                    null,
                    LoginContextHolder.me().getSysLoginUserId(),
                    tsv.getSettlementTime(),
                    LoginContextHolder.me().getTenantId());
            fs.setChannel(tsv.getChannel());
            financeSettlementMapper.insert(fs);
            if (tsv.getImgList() != null && tsv.getImgList().size() > 0) {
                // 结算图片保存
                for (String url : tsv.getImgList()) {
                    FinanceSettlementImage image = new FinanceSettlementImage();
                    image.setSettlementId(fs.getId());
                    image.setUrl(url);
                    financeSettlementImageMapper.insert(image);
                }
            }
        }
        // 结算状态变更
        changeFinanceStatus(tsv.getOrderId());
    }

    @Override
    public String getSettlementIdByTransportNo(String transportNo) {
        return financeCheckMapper.getSettlementIdByTransportNo(transportNo);
    }

    @Override
    public List<FinanceDetail> getCheckFinanceDetail(FinanceDTO financeDTO) {
        return financeDetailMapper.getCheckFinanceDetail(financeDTO, businessUtil.getTenantId());
    }

    @Override
    public void dealCheckSettlement(List<FinanceDetail> list, List<PkgFinanceCheck> checkList, FinanceCheckVO
            financeCheckVO) {
        Set<Long> orderIdSet = new HashSet<>();
        // 对账单结算记录
        FinanceCheck financeCheck = new FinanceCheck();

        List<String> userNameList = list.stream().map(FinanceDetail::getSettlementUser).distinct().collect(Collectors.toList());
        financeCheck.setSettlementUser(String.join(",", userNameList));
        financeCheck.setTenantId(businessUtil.getTenantId());
        //financeCheck.setSettlementPhone(list.get(0).getSettlementPhone());
        financeCheck.setImages(String.join(",", financeCheckVO.getImageList()));
        financeCheck.setRemark(financeCheckVO.getRemark());
        financeCheck.setRealCollectionTime(financeCheckVO.getRealCollectionTime());
        financeCheck.setTotalCollectionUn(new BigDecimal(list.stream().filter(e -> e.getType() < 5).mapToDouble(e -> e.getUnSettlement() == null ? 0.0 : e.getUnSettlement().doubleValue()).reduce(0, Double::sum)));
        financeCheck.setTotalPaymentUn(new BigDecimal(list.stream().filter(e -> e.getType() >= 5).mapToDouble(e -> e.getUnSettlement() == null ? 0.0 : e.getUnSettlement().doubleValue()).reduce(0, Double::sum)));
        financeCheck.setTotalCheck(financeCheck.getTotalCollectionUn().subtract(financeCheck.getTotalPaymentUn()));
        financeCheckMapper.insert(financeCheck);
        for (FinanceDetail fd : list) {
            // 对账单结算明细
            FinanceCheckDetail fcd = new FinanceCheckDetail();
            fcd.setFinanceCheckId(financeCheck.getId());
            fcd.setFinanceDetailId(fd.getId());
            fcd.setType(fd.getType());
            fcd.setOrderId(fd.getOrderId());
            fcd.setUnSettlement(fd.getUnSettlement());
            fcd.setOperatorUser(LoginContextHolder.me().getSysLoginUserId());
            fcd.setRemark(financeCheckVO.getRemark());
            fcd.setTenantId(businessUtil.getTenantId());
            fcd.setRelationId(fd.getRelationId());
            fcd.setRealCollectionTime(financeCheckVO.getRealCollectionTime());
            fcd.setChannel(financeCheckVO.getChannel());
            if (fd.getType() == 1 || fd.getType() == 2 || fd.getType() == 3 || fd.getType() == 4) {
                fcd.setCheckFee(fd.getUnSettlement());
            } else {
                fcd.setCheckFee(BigDecimal.ZERO.subtract(fd.getUnSettlement()));
            }
            fcd.setStatus(PublicCommon.已结算);
            financeCheckDetailMapper.insert(fcd);
            // financeDetail 结算状态变更
            fd.setStatus(2);
            financeDetailMapper.updateById(fd);
            Long operatorUser = LoginContextHolder.me().getSysLoginUserId();
            Date realCollectionTime = financeCheckVO.getRealCollectionTime(); //DateUtil.format(financeCheckVO.getRealCollectionTime(), "yyyy-MM-dd HH:mm:ss");
            //费用类型：1.现付收款 2.到付收款 3.欠付收款 4.月结收款 5.商务付款 6.提车付款 7.送车付款 8.承运付款 9.其他付款',
            switch (fd.getType()) {
                case 1:
                    spotSettlement(new SettlementVO(fd.getOrderId(), null, 1, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 2:
                    deliverySettlement(new SettlementVO(fd.getOrderId(), null, 2, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 3:
                    backSettlement(new SettlementVO(fd.getOrderId(), null, 3, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 4:
                    slotSettlement(new SettlementVO(fd.getOrderId(), null, 4, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 5:
                    kickbackSettlement(new SettlementVO(fd.getOrderId(), null, 5, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 6:
                    pickSettlement(new SettlementVO(fd.getOrderId(), null, 6, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 7:
                    takeSettlement(new SettlementVO(fd.getOrderId(), null, 7, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 8:
                    transportSettlementSingle(new TransportSettlementVO(fd.getRelationId(), fd.getOrderId(), fd.getRelationId(), fd.getUnSettlement(), null, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 9:
                    extraSettlementSingle(new TransportSettlementVO(fd.getRelationId(), fd.getOrderId(), fd.getRelationId(), fd.getUnSettlement(), null, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
            }
            orderIdSet.add(fd.getOrderId());
        }
        if (orderIdSet != null && orderIdSet.size() > 0) {
            // 结算状态变更
            for (Long orderId : orderIdSet) {
                changeFinanceStatus(orderId);
            }
        }
    }


    @Override
    public void dealCheckSettlement2
            (List<FinanceDetail> list, List<PkgFinanceCheck> checkList, FinanceCheckVO financeCheckVO) {

        // 对账单结算记录
        FinanceCheck financeCheck = new FinanceCheck();

        List<String> userNameList = list.stream().map(FinanceDetail::getSettlementUser).distinct().collect(Collectors.toList());
        financeCheck.setSettlementUser(String.join(",", userNameList));
        financeCheck.setTenantId(businessUtil.getTenantId());
        //financeCheck.setSettlementPhone(list.get(0).getSettlementPhone());
  /*      financeCheck.setImages(String.join(",", financeCheckVO.getImageList()));
        financeCheck.setRemark(financeCheckVO.getRemark());
        financeCheck.setRealCollectionTime(financeCheckVO.getRealCollectionTime());*/

        financeCheck.setTotalCollectionUn(new BigDecimal(list.stream().filter(e -> e.getType() < 5).mapToDouble(e -> e.getUnSettlement() == null ? 0.0 : e.getUnSettlement().doubleValue()).reduce(0, Double::sum)));
        financeCheck.setTotalPaymentUn(new BigDecimal(list.stream().filter(e -> e.getType() >= 5).mapToDouble(e -> e.getUnSettlement() == null ? 0.0 : e.getUnSettlement().doubleValue()).reduce(0, Double::sum)));
        financeCheck.setTotalCheck(financeCheck.getTotalCollectionUn().subtract(financeCheck.getTotalPaymentUn()));
        financeCheckMapper.insert(financeCheck);
        for (FinanceDetail fd : list) {
            // 对账单结算明细
            FinanceCheckDetail fcd = new FinanceCheckDetail();
            fcd.setFinanceCheckId(financeCheck.getId());
            fcd.setFinanceDetailId(fd.getId());
            fcd.setType(fd.getType());
            fcd.setOrderId(fd.getOrderId());
            fcd.setUnSettlement(fd.getUnSettlement());
            fcd.setOperatorUser(LoginContextHolder.me().getSysLoginUserId());
            fcd.setRemark(financeCheckVO.getRemark());
            fcd.setTenantId(businessUtil.getTenantId());
            fcd.setRelationId(fd.getRelationId());
       /*     fcd.setRealCollectionTime(financeCheckVO.getRealCollectionTime());
            fcd.setChannel(financeCheckVO.getChannel());*/
            if (fd.getType() == 1 || fd.getType() == 2 || fd.getType() == 3 || fd.getType() == 4) {
                fcd.setCheckFee(fd.getUnSettlement());
            } else {
                fcd.setCheckFee(BigDecimal.ZERO.subtract(fd.getUnSettlement()));
            }
            fcd.setStatus(PublicCommon.未结算);
            financeCheckDetailMapper.insert(fcd);
            // financeDetail 结算状态变更
            fd.setStatus(2);
            financeDetailMapper.updateById(fd);
        }
    }

    @Override
    public void settlementFincecheck(FinanceCheckVO financeCheckVO) {
        List<Long> list = financeCheckVO.getFinanceCheckIdList();
        List<FinanceCheckDetail> financeCheckDetails = financeCheckDetailMapper.selectList(new QueryWrapper<FinanceCheckDetail>().lambda()
                .eq(FinanceCheckDetail::getStatus, PublicCommon.未结算).in(FinanceCheckDetail::getId, list));

        if (financeCheckDetails.isEmpty()) {
            return;
        }

        FinanceCheck financeCheck = new FinanceCheck();
        FinanceCheck financeCheck1 = financeCheckMapper.selectById(financeCheckDetails.get(0).getFinanceCheckId());
        financeCheck.setId(financeCheckDetails.get(0).getFinanceCheckId());
        if (financeCheckVO.getImageList() != null && financeCheckVO.getImageList().size() > 0) {
            if (StringUtils.isNotBlank(financeCheck1.getImages())) {
                financeCheck.setImages(financeCheck1.getImages() + "," + String.join(",", financeCheckVO.getImageList()));
            } else if (StringUtils.isBlank(financeCheck1.getImages())) {
                financeCheck.setImages(String.join(",", financeCheckVO.getImageList()));
            }
        }

        financeCheck.setRemark(financeCheckVO.getRemark());
        financeCheck.setRealCollectionTime(financeCheckVO.getRealCollectionTime());
        financeCheckMapper.updateById(financeCheck);

        OrderFinishRecordVO orderFinishRecordVO = new OrderFinishRecordVO();

        Set<Long> orderIdSet = new HashSet<>();
        List<FinanceCheckDetail> newFincecheckDetailList = financeCheckDetailMapper.selectBatchIds(list);
        for (FinanceCheckDetail fd : financeCheckDetails) {

            TransportLevelDetail transportLevelDetail = transportLevelDetailMapper.selectOne(new QueryWrapper<TransportLevelDetail>().lambda()
                    .eq(TransportLevelDetail::getOrderId, fd.getOrderId())
                    .last("limit 1"));
            if (transportLevelDetail != null) {
                orderFinishRecordVO.setLevelId(transportLevelDetail.getLevelId());
                if (finishService.checkLevelFinish(orderFinishRecordVO, new StringBuilder())) {
                    finishService.levelFinish(orderFinishRecordVO);
                }
            }

            FinanceCheckDetail financeCheckDetail = new FinanceCheckDetail();
            financeCheckDetail.setId(fd.getId());
            financeCheckDetail.setRealCollectionTime(financeCheckVO.getRealCollectionTime());
            financeCheckDetail.setChannel(financeCheckVO.getChannel());
            financeCheckDetail.setStatus(PublicCommon.已结算);
            newFincecheckDetailList.add(financeCheckDetail);

            Long operatorUser = LoginContextHolder.me().getSysLoginUserId();
            Date realCollectionTime = financeCheckVO.getRealCollectionTime();
            //DateUtil.format(financeCheckVO.getRealCollectionTime(), "yyyy-MM-dd HH:mm:ss");
            //费用类型：1.现付收款 2.到付收款 3.欠付收款 4.月结收款 5.商务付款 6.提车付款 7.送车付款 8.承运付款 9.其他付款',
            switch (fd.getType()) {
                case 1:
                    spotSettlement(new SettlementVO(fd.getOrderId(), null, 1, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 2:
                    deliverySettlement(new SettlementVO(fd.getOrderId(), null, 2, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 3:
                    backSettlement(new SettlementVO(fd.getOrderId(), null, 3, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 4:
                    slotSettlement(new SettlementVO(fd.getOrderId(), null, 4, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 5:
                    kickbackSettlement(new SettlementVO(fd.getOrderId(), null, 5, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 6:
                    pickSettlement(new SettlementVO(fd.getOrderId(), null, 6, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 7:
                    takeSettlement(new SettlementVO(fd.getOrderId(), null, 7, fd.getUnSettlement(), null, operatorUser, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 8:
                    transportSettlementSingle(new TransportSettlementVO(fd.getRelationId(), fd.getOrderId(), fd.getRelationId(), fd.getUnSettlement(), null, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
                case 9:
                    extraSettlementSingle(new TransportSettlementVO(fd.getRelationId(), fd.getOrderId(), fd.getRelationId(), fd.getUnSettlement(), null, financeCheckVO.getRemark(), realCollectionTime, financeCheckVO.getChannel()), 1, financeCheck.getId());
                    break;
            }
            orderIdSet.add(fd.getOrderId());
        }
        if (orderIdSet != null && orderIdSet.size() > 0) {
            // 结算状态变更
            for (Long orderId : orderIdSet) {
                changeFinanceStatus(orderId);
            }
        }
        financeCheckDetailService.updateBatchById(newFincecheckDetailList);
    }


    public void extraSettlementSingle(TransportSettlementVO transportSettlementVO, Integer origin, Long checkId) {
        OrderExtraFee oef = orderExtraFeeMapper.selectById(transportSettlementVO.getTransportId());
        if (oef != null) {
            oef.setHasSettlement(oef.getHasSettlement().add(transportSettlementVO.getSettlementFee()));
            oef.setUnSettlement(oef.getUnSettlement().subtract(transportSettlementVO.getSettlementFee()));
            orderExtraFeeMapper.updateById(oef);
        }
        // 结算明细及结算记录
        FinanceDetail fd = financeDetailMapper.getByOrderIdAndRelationId(9, transportSettlementVO.getOrderId(), transportSettlementVO.getTransportId());
        if (fd != null) {
            fd.setHasSettlement(fd.getHasSettlement().add(transportSettlementVO.getSettlementFee()));
            fd.setUnSettlement(fd.getUnSettlement().subtract(transportSettlementVO.getSettlementFee()));
            financeDetailMapper.updateById(fd);
        }
        FinanceSettlement fs = new FinanceSettlement(
                transportSettlementVO.getOrderId(),
                transportSettlementVO.getTransportId(),
                oef.getId(),
                transportSettlementVO.getSettlementFee(),
                fd.getSettlementUser(),
                fd.getSettlementPhone(),
                9,
                transportSettlementVO.getRemark(),
                origin,
                checkId,
                LoginContextHolder.me().getSysLoginUserId(),
                transportSettlementVO.getSettlementTime(),
                LoginContextHolder.me().getTenantId());
        fs.setChannel(transportSettlementVO.getChannel());
        financeSettlementMapper.insert(fs);
        if (transportSettlementVO.getImgList() != null && transportSettlementVO.getImgList().size() > 0) {
            // 结算图片保存
            for (String url : transportSettlementVO.getImgList()) {
                FinanceSettlementImage image = new FinanceSettlementImage();
                image.setSettlementId(fs.getId());
                image.setUrl(url);
                financeSettlementImageMapper.insert(image);
            }
        }
    }


    public void transportSettlementSingle(TransportSettlementVO transportSettlementVO, Integer origin, Long checkId) {
        FinanceTransport ft = financeTransportMapper.getByOrderIdAndTransportId(transportSettlementVO.getOrderId(), transportSettlementVO.getTransportId());
        if (ft != null) {
            ft.setTransportHas(ft.getTransportHas().add(transportSettlementVO.getSettlementFee()));
            ft.setTransportUn(ft.getTransportUn().subtract(transportSettlementVO.getSettlementFee()));
            financeTransportMapper.updateById(ft);
        }
        // 结算明细及结算记录
        FinanceDetail fd = financeDetailMapper.getByOrderIdAndRelationId(8, transportSettlementVO.getOrderId(), transportSettlementVO.getTransportId());
        if (fd != null) {
            fd.setHasSettlement(fd.getHasSettlement().add(transportSettlementVO.getSettlementFee()));
            fd.setUnSettlement(fd.getUnSettlement().subtract(transportSettlementVO.getSettlementFee()));
            financeDetailMapper.updateById(fd);
        }
        FinanceSettlement fs = new FinanceSettlement(
                transportSettlementVO.getOrderId(),
                transportSettlementVO.getTransportId(),
                null,
                transportSettlementVO.getSettlementFee(),
                fd.getSettlementUser(),
                fd.getSettlementPhone(),
                8,
                transportSettlementVO.getRemark(),
                origin,
                checkId,
                LoginContextHolder.me().getSysLoginUserId(),
                transportSettlementVO.getSettlementTime(),
                LoginContextHolder.me().getTenantId());
        fs.setChannel(transportSettlementVO.getChannel());
        fs.setTenantId(businessUtil.getTenantId());
        financeSettlementMapper.insert(fs);
        if (transportSettlementVO.getImgList() != null && transportSettlementVO.getImgList().size() > 0) {
            // 结算图片保存
            for (String url : transportSettlementVO.getImgList()) {
                FinanceSettlementImage image = new FinanceSettlementImage();
                image.setSettlementId(fs.getId());
                image.setUrl(url);
                image.setTenantId(businessUtil.getTenantId());
                financeSettlementImageMapper.insert(image);
            }
        }
    }

    @Override
    public void exportCheckExcel(FinanceDTO financeDTO, HttpServletResponse response) {
        // 数据组织
        List<PkgFinanceCheck> list = financeMapper.getFinanceCheckList(financeDTO, businessUtil.getTenantId());
        if (list != null && list.size() > 0) {
            List<PkgFinanceCheckExport> listExport = new ArrayList<>();
            for (PkgFinanceCheck financeCheck : list) {
                financeCheck.setStartCode(cmCityMapper.getNameByCode(financeCheck.getStartCode()));
                financeCheck.setDestinationCode(cmCityMapper.getNameByCode(financeCheck.getDestinationCode()));
                PkgFinanceCheckExport export = new PkgFinanceCheckExport();
                BeanUtils.copyProperties(financeCheck, export);
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                export.setCreateTime(sdf.format(financeCheck.getCreateTime()));
                if (financeCheck.getTransportTime() != null) {
                    export.setTransportTime(sdf.format(financeCheck.getTransportTime()));
                }
                listExport.add(export);
            }
            List<ExcelHeaderInfo> headerInfos = Arrays.asList(new ExcelHeaderInfo(0, 1, 0, 24, "对账单"));
            ExcelUtils excelUtils = new ExcelUtils(listExport, getHeadInfo(), headerInfos, getFormatInfo());
            excelUtils.sendHttpResponse(response, "对账单" + SnowIdUtils.uniqueLong(), excelUtils.getWorkbook());
        }
    }

    private Map<String, ExcelFormat> getFormatInfo() {
        Map<String, ExcelFormat> format = new HashMap<>();
        format.put("totalFee", ExcelFormat.FORMAT_NUMBER);
        format.put("totalCollectionHas", ExcelFormat.FORMAT_NUMBER);
        format.put("totalCollectionUn", ExcelFormat.FORMAT_NUMBER);
        format.put("spotHas", ExcelFormat.FORMAT_NUMBER);
        format.put("spotUn", ExcelFormat.FORMAT_NUMBER);
        format.put("deliveryHas", ExcelFormat.FORMAT_NUMBER);
        format.put("deliveryUn", ExcelFormat.FORMAT_NUMBER);
        format.put("backHas", ExcelFormat.FORMAT_NUMBER);
        format.put("backUn", ExcelFormat.FORMAT_NUMBER);
        format.put("slotHas", ExcelFormat.FORMAT_NUMBER);
        format.put("slotUn", ExcelFormat.FORMAT_NUMBER);
        format.put("unCollection", ExcelFormat.FORMAT_NUMBER);
        format.put("kickbackUn", ExcelFormat.FORMAT_NUMBER);
        format.put("pickUn", ExcelFormat.FORMAT_NUMBER);
        format.put("transportUn", ExcelFormat.FORMAT_NUMBER);
        format.put("takeUn", ExcelFormat.FORMAT_NUMBER);
        format.put("otherUn", ExcelFormat.FORMAT_NUMBER);
        format.put("unPayment", ExcelFormat.FORMAT_NUMBER);
        format.put("financeCheck", ExcelFormat.FORMAT_NUMBER);
        format.put("createTime", ExcelFormat.FORMAT_DATE);
        format.put("lastFollowTime", ExcelFormat.FORMAT_DATE);
        format.put("origin", ExcelFormat.FORMAT_CUSTOMER_ORIGIN);
        format.put("callStatus", ExcelFormat.FORMAT_CUSTOMER_CALL_STATUS);
        format.put("status", ExcelFormat.FORMAT_CUSTOMER_STATUS);
        format.put("pickCarType", ExcelFormat.FORMAT_PICK_CAR_TYPE);
        format.put("takeCarType", ExcelFormat.FORMAT_TAKE_CAR_TYPE);
        format.put("orderStatus", ExcelFormat.FORMAT_ORDER_STATUS);
        format.put("orderTransportType", ExcelFormat.FORMAT_ORDER_TRANSPORT_TYPE);
        format.put("paymentType", ExcelFormat.FORMAT_PAYMENT_TYPE);
        format.put("transportTime", ExcelFormat.FORMAT_DATE);
        format.put("transportType", ExcelFormat.FORMAT_ORDER_TRANSPORT_TYPE);
        return format;
    }

    private List<ExcelHeaderInfo> getHeadInfo() {
        return Arrays.asList(
                new ExcelHeaderInfo(3, 3, 0, 0, "子订单号"),
                new ExcelHeaderInfo(3, 3, 1, 1, "运单号"),
                new ExcelHeaderInfo(3, 3, 2, 2, "大板车牌"),
                new ExcelHeaderInfo(3, 3, 3, 3, "制单人"),
                new ExcelHeaderInfo(3, 3, 4, 4, "制单时间"),
                new ExcelHeaderInfo(3, 3, 5, 5, "客户"),
                new ExcelHeaderInfo(3, 3, 6, 6, "联系方式"),
                new ExcelHeaderInfo(3, 3, 7, 7, "收货人"),
                new ExcelHeaderInfo(3, 3, 8, 8, "联系方式"),
                new ExcelHeaderInfo(3, 3, 9, 9, "出发地"),
                new ExcelHeaderInfo(3, 3, 10, 10, "目的地"),
                new ExcelHeaderInfo(3, 3, 11, 11, "运输方式"),
                new ExcelHeaderInfo(3, 3, 12, 12, "车型"),
                new ExcelHeaderInfo(3, 3, 13, 13, "车架号"),
                new ExcelHeaderInfo(3, 3, 14, 14, "未收运费"),
                new ExcelHeaderInfo(3, 3, 15, 15, "未付商务费"),
                new ExcelHeaderInfo(3, 3, 16, 16, "未付提车费"),
                new ExcelHeaderInfo(3, 3, 17, 17, "未付承运费"),
                new ExcelHeaderInfo(3, 3, 18, 18, "未付送车费"),
                new ExcelHeaderInfo(3, 3, 19, 19, "未付其他费用"),
                new ExcelHeaderInfo(3, 3, 20, 20, "未付费用合计"),
                new ExcelHeaderInfo(3, 3, 21, 21, "应结款"),
                new ExcelHeaderInfo(3, 3, 22, 22, "订单备注"),
                new ExcelHeaderInfo(3, 3, 23, 23, "发车时间"),
                new ExcelHeaderInfo(3, 3, 24, 24, "司机")
        );
    }

    private List<ExcelHeaderInfo> getCollectionHeadInfo() {
        return Arrays.asList(
                new ExcelHeaderInfo(2, 2, 0, 0, "订单状态"),
                new ExcelHeaderInfo(2, 2, 1, 1, "制单人"),
                new ExcelHeaderInfo(2, 2, 2, 2, "客户"),
                new ExcelHeaderInfo(2, 2, 3, 3, "联系方式"),
                new ExcelHeaderInfo(2, 2, 4, 4, "收货人"),
                new ExcelHeaderInfo(2, 2, 5, 5, "联系方式"),
                new ExcelHeaderInfo(2, 2, 6, 6, "子订单号"),
                new ExcelHeaderInfo(2, 2, 7, 7, "制单时间"),
                new ExcelHeaderInfo(2, 2, 8, 8, "出发地"),
                new ExcelHeaderInfo(2, 2, 9, 9, "目的地"),
                new ExcelHeaderInfo(2, 2, 10, 10, "车型"),
                new ExcelHeaderInfo(2, 2, 11, 11, "车架号"),
                new ExcelHeaderInfo(2, 2, 12, 12, "付款方式"),
                new ExcelHeaderInfo(2, 2, 13, 13, "总运费"),
                new ExcelHeaderInfo(2, 2, 14, 14, "已收合计"),
                new ExcelHeaderInfo(2, 2, 15, 15, "未收合计"),
                new ExcelHeaderInfo(2, 2, 16, 16, "现付已收"),
                new ExcelHeaderInfo(2, 2, 17, 17, "现付未收"),
                new ExcelHeaderInfo(2, 2, 18, 18, "到付已收"),
                new ExcelHeaderInfo(2, 2, 19, 19, "到付未收"),
                new ExcelHeaderInfo(2, 2, 20, 20, "欠付已收"),
                new ExcelHeaderInfo(2, 2, 21, 21, "欠付未收"),
                new ExcelHeaderInfo(2, 2, 22, 22, "月结已收"),
                new ExcelHeaderInfo(2, 2, 23, 23, "月结未收"),
                new ExcelHeaderInfo(2, 2, 24, 24, "订单备注")
        );
    }

    private List<ExcelHeaderInfo> getPaymentHeadInfo() {
        return Arrays.asList(
                new ExcelHeaderInfo(2, 2, 0, 0, "子订单号"),
                new ExcelHeaderInfo(2, 2, 1, 1, "制单时间"),
                new ExcelHeaderInfo(2, 2, 2, 2, "出发地"),
                new ExcelHeaderInfo(2, 2, 3, 3, "目的地"),
                new ExcelHeaderInfo(2, 2, 4, 4, "车型"),
                new ExcelHeaderInfo(2, 2, 5, 5, "车架号"),
                new ExcelHeaderInfo(2, 2, 6, 6, "应付合计"),
                new ExcelHeaderInfo(2, 2, 7, 7, "已付合计"),
                new ExcelHeaderInfo(2, 2, 8, 8, "未付合计"),
                new ExcelHeaderInfo(2, 2, 9, 9, "商务费应付"),
                new ExcelHeaderInfo(2, 2, 10, 10, "商务费已付"),
                new ExcelHeaderInfo(2, 2, 11, 11, "商务费未付"),
                new ExcelHeaderInfo(2, 2, 12, 12, "结算人"),
                new ExcelHeaderInfo(2, 2, 13, 13, "电话"),
                new ExcelHeaderInfo(2, 2, 14, 14, "提车费应付"),
                new ExcelHeaderInfo(2, 2, 15, 15, "提车费已付"),
                new ExcelHeaderInfo(2, 2, 16, 16, "提车费未付"),
                new ExcelHeaderInfo(2, 2, 17, 17, "结算人"),
                new ExcelHeaderInfo(2, 2, 18, 18, "电话"),
                new ExcelHeaderInfo(2, 2, 19, 19, "承运费应付"),
                new ExcelHeaderInfo(2, 2, 20, 20, "承运费已付"),
                new ExcelHeaderInfo(2, 2, 21, 21, "承运费未付"),
                new ExcelHeaderInfo(2, 2, 22, 22, "送货费应付"),
                new ExcelHeaderInfo(2, 2, 23, 23, "送货费已付"),
                new ExcelHeaderInfo(2, 2, 24, 24, "送货费未付"),
                new ExcelHeaderInfo(2, 2, 25, 25, "结算人"),
                new ExcelHeaderInfo(2, 2, 26, 26, "电话"),
                new ExcelHeaderInfo(2, 2, 27, 27, "其他费用应付"),
                new ExcelHeaderInfo(2, 2, 28, 28, "其他费用已付"),
                new ExcelHeaderInfo(2, 2, 29, 29, "其他费用未付"),
                new ExcelHeaderInfo(2, 2, 30, 30, "订单状态"),
                new ExcelHeaderInfo(2, 2, 31, 31, "制单人"),
                new ExcelHeaderInfo(2, 2, 32, 32, "客户"),
                new ExcelHeaderInfo(2, 2, 33, 33, "联系方式"),
                new ExcelHeaderInfo(2, 2, 34, 34, "收货人"),
                new ExcelHeaderInfo(2, 2, 35, 35, "联系方式"),
                new ExcelHeaderInfo(2, 2, 36, 36, "订单备注")
        );
    }

    @Override
    public void exportCheckDetailExcel(String id, HttpServletResponse response) {
        // 数据组织
        FinanceCheck fc = financeCheckMapper.selectById(id);
        List<PkgFinanceCheck> list = financeCheckMapper.getPkgFinanceCheckListById(id, businessUtil.getTenantId());
        if (list != null && list.size() > 0) {
            List<PkgFinanceCheckExport> listExport = new ArrayList<>();
            for (PkgFinanceCheck financeCheck : list) {
                financeCheck.setStartCode(cmCityMapper.getNameByCode(financeCheck.getStartCode()));
                financeCheck.setDestinationCode(cmCityMapper.getNameByCode(financeCheck.getDestinationCode()));
                PkgFinanceCheckExport export = new PkgFinanceCheckExport();
                BeanUtils.copyProperties(financeCheck, export);

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                export.setCreateTime(sdf.format(financeCheck.getCreateTime()));
                if (financeCheck.getTransportTime() != null) {
                    export.setTransportTime(sdf.format(financeCheck.getTransportTime()));
                }
                listExport.add(export);
            }
            List<ExcelHeaderInfo> headerInfos = Arrays.asList(
                    new ExcelHeaderInfo(0, 1, 0, 23, "对账单"),
                    new ExcelHeaderInfo(2, 2, 0, 23, "结算人：" + fc.getSettlementUser() + " 联系方式：" +
                            fc.getSettlementPhone() + "  结算时间：" + DateUtil.format(fc.getCreateTime(), "yyyy-MM-dd HH:mm:ss")));
            ExcelUtils excelUtils = new ExcelUtils(listExport, getHeadInfo(), headerInfos, getFormatInfo());
            excelUtils.sendHttpResponse(response, "对账单" + SnowIdUtils.uniqueLong(), excelUtils.getWorkbook());
        }
    }

    @Override
    public ResponseData getFinanceCheckListPage(Page<Object> defaultPage, FinanceDTO financeDTO) {
        AndaPageResult pageResult = new AndaPageResult();
        Page<FinanceCheck> list = financeCheckMapper.getFinanceCheckListPage(defaultPage, financeDTO, businessUtil.getTenantId());
        pageResult.AndaPageResult(list, financeDTO);
        // 合计行
        pageResult.setSummary(financeCheckMapper.getFinanceCheckSummary(financeDTO, businessUtil.getTenantId()));
        return ResponseData.andaSuccess(pageResult);
    }

    @Override
    public FinanceCheck getFinanceCheckDetail(String id) {
        FinanceCheck financeCheck = financeCheckMapper.selectById(id);
        if (financeCheck != null) {
            financeCheck.setCheckOrderList(financeCheckMapper.getPkgFinanceCheckListById(id, businessUtil.getTenantId()));
        }
        return financeCheck;
    }

    @Override
    public PageResult<PkgFinanceSettlement> getFinanceSettlementList(Page page, SettlementVO settlementVO) {
        Page<PkgFinanceSettlement> pkgFinanceSettlementPage = financeSettlementMapper.getListBySettlementVO(page, settlementVO, businessUtil.getTenantId());
        // 对账单结算图片
        if (pkgFinanceSettlementPage != null && pkgFinanceSettlementPage.getRecords().size() > 0) {
            for (PkgFinanceSettlement fs : pkgFinanceSettlementPage.getRecords()) {
                // 结算图片
                fs.setImgList(financeSettlementImageMapper.getSettlementImage(fs.getId()));
                // 对账单结算图片处理
                if (fs.getOrigin() == 1 && StringUtils.isNotBlank(fs.getCheckId())) {
                    FinanceCheck fc = financeCheckMapper.selectById(fs.getCheckId());
                    fs.setImgList(new ArrayList<>(Arrays.asList(fc.getImages().split(","))));
                }
                // 到付 交付回单凭证处理
                if (fs.getType() == 2) {
                    List<String> imgList = orderFinishImageMapper.getImageByOrderIdAndType(fs.getOrderId(), 2);
                    fs.getImgList().addAll(imgList);
                }
                // 到付线上支付数据处理
                if (fs.getOrigin() == 2) {
                    // 交付信息
                    PkgOrderFinishRecord pkgOrderFinishRecord = orderFinishRecordMapper.getPkgOrderFinishRecordDetailByOrderId(fs.getOrderId());
                    // 线上支付信息
                    if (pkgOrderFinishRecord != null) {
                        if (pkgOrderFinishRecord.getType() != null &&
                                pkgOrderFinishRecord.getType() == 1 && StringUtils.isNotBlank(pkgOrderFinishRecord.getClientSn())) {
                            PkgOnlinePayRecord onlinePayRecord = orderPayRecordMapper.getSuccessRecordByClientSn(pkgOrderFinishRecord.getClientSn());
                            fs.setOnlinePayData(onlinePayRecord);
                        }
                    }
                }
                // 承运费路线处理
                if (fs.getType() == FinanceTypeEnum.TRANSPORT.type) {
                    PkgTransportLevelDetailSimple transport = transportLevelDetailMapper.getPkgTransportLevelDetailSimpleByOrderIdAndTransportId(fs.getOrderId(), fs.getTransportId());
                    if (transport != null) {
                        fs.setStartCode(transport.getStartCode());
                        fs.setDestinationCode(transport.getDestinationCode());
                    }
                }
            }
        }
        return new PageResult<>(pkgFinanceSettlementPage);
    }

    @Override
    public boolean checkFinanceSettlementUpdate(FinanceSettlement financeSettlement, StringBuilder errorMsg) {
        if (financeSettlement == null || financeSettlement.getId() == null) {
            errorMsg.append("请求参数错误，请检查参数");
            return false;
        }
        FinanceSettlement fs = financeSettlementMapper.selectById(financeSettlement.getId());
        if (fs.getOrigin() != 0) {
            errorMsg.append("非手动结算，不可修改");
            return false;
        }
        if (fs.getStatus() == 1) {
            errorMsg.append("当前结算记录已作废，不可修改！");
            return false;
        }
        //最大可修改结算金额 = 未结算金额 + 当前结算金额
        FinanceDetail fd;
        if (fs.getType() == 8) {
            fd = financeDetailMapper.getByOrderIdAndRelationId(fs.getType(), fs.getOrderId(), fs.getTransportId());
        } else if (fs.getType() == 9) {
            fd = financeDetailMapper.getByOrderIdAndRelationId(fs.getType(), fs.getOrderId(), fs.getOrderExtraFeeId());
        } else {
            fd = financeDetailMapper.getByOrderIdAndType(fs.getOrderId(), fs.getType());
        }
        BigDecimal canUpdateFee = fd.getUnSettlement().add(fs.getSettlementFee());
        if (financeSettlement.getSettlementFee().compareTo(canUpdateFee) > 0) {
            errorMsg.append("结算金额不可大于未结算金额");
            return false;
        }
        return true;
    }

    @Override
    public void updateFinanceSettlement(FinanceSettlement financeSettlement) {
        FinanceSettlement fs = financeSettlementMapper.selectById(financeSettlement.getId());
        financeSettlement.setType(fs.getType());
        financeSettlement.setOrderId(fs.getOrderId());
        financeSettlement.setTransportId(fs.getTransportId());
        financeSettlement.setOrderExtraFeeId(fs.getOrderExtraFeeId());
        // 之前的结算记录作废
        financeSettlementMapper.updateStatusById(financeSettlement.getId(), YesOrNoEnum.YES.type);
        // 插入新的结算记录
        FinanceSettlement newFs = new FinanceSettlement();
        newFs.setOrderId(fs.getOrderId());
        newFs.setSettlementFee(financeSettlement.getSettlementFee());
        newFs.setSettlementUser(fs.getSettlementUser());
        newFs.setSettlementPhone(fs.getSettlementPhone());
        newFs.setTransportId(fs.getTransportId());
        newFs.setType(fs.getType());
        newFs.setOrigin(0);
        newFs.setStatus(0);
        newFs.setChannel(financeSettlement.getChannel());
        newFs.setSettlementTime(financeSettlement.getSettlementTime());
        newFs.setTenantId(LoginContextHolder.me().getTenantId());
        financeSettlementMapper.insert(newFs);
        // 结算凭证
        if (financeSettlement.getImgList() != null && financeSettlement.getImgList().size() > 0) {
            // 结算图片保存
            for (String url : financeSettlement.getImgList()) {
                FinanceSettlementImage image = new FinanceSettlementImage();
                image.setSettlementId(newFs.getId());
                image.setUrl(url);
                financeSettlementImageMapper.insert(image);
            }
        }
        // 修改账单
        // 本次结算金额 - 修改前结算金额 = 差额
        BigDecimal balance = financeSettlement.getSettlementFee().subtract(fs.getSettlementFee());
        if (fs.getSettlementFee().compareTo(financeSettlement.getSettlementFee()) != 0) {
            switch (fs.getType()) {
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    updateSpotSettlement(financeSettlement, balance);
                    break;
                case 8:
                    updateTransportSettlement(financeSettlement, balance);
                    break;
                case 9:
                    updateOtherSettlement(financeSettlement, balance);
                    break;
            }
            // 结算状态变更
            changeFinanceStatus(fs.getOrderId());
        }
    }

    private void updateOtherSettlement(FinanceSettlement financeSettlement, BigDecimal balance) {
        OrderExtraFee oef = orderExtraFeeMapper.selectById(financeSettlement.getOrderExtraFeeId());
        if (oef != null) {
            oef.setHasSettlement(oef.getHasSettlement().add(balance));
            oef.setUnSettlement(oef.getUnSettlement().subtract(balance));
            orderExtraFeeMapper.updateById(oef);
        }
        // 结算明细及结算记录
        FinanceDetail fd = financeDetailMapper.getByOrderIdAndRelationId(9, financeSettlement.getOrderId(), financeSettlement.getOrderExtraFeeId());
        if (fd != null) {
            fd.setHasSettlement(fd.getHasSettlement().add(balance));
            fd.setUnSettlement(fd.getUnSettlement().subtract(balance));
            fd.setStatus(1);
            if (fd.getUnSettlement().compareTo(BigDecimal.ZERO) == 0) {
                fd.setStatus(2);
            }
            financeDetailMapper.updateById(fd);
        }
    }

    private void updateTransportSettlement(FinanceSettlement financeSettlement, BigDecimal balance) {
        FinanceTransport ft = financeTransportMapper.getByOrderIdAndTransportId(financeSettlement.getOrderId(), financeSettlement.getTransportId());
        if (ft != null) {
            ft.setTransportHas(ft.getTransportHas().add(balance));
            ft.setTransportUn(ft.getTransportUn().subtract(balance));
            financeTransportMapper.updateById(ft);
        }
        // 结算明细及结算记录
        FinanceDetail fd = financeDetailMapper.getByOrderIdAndRelationId(8, financeSettlement.getOrderId(), financeSettlement.getTransportId());
        if (fd != null) {
            fd.setHasSettlement(fd.getHasSettlement().add(balance));
            fd.setUnSettlement(fd.getUnSettlement().subtract(balance));
            fd.setStatus(1);
            if (fd.getUnSettlement().compareTo(BigDecimal.ZERO) == 0) {
                fd.setStatus(2);
            }
            financeDetailMapper.updateById(fd);
        }
    }


    private void updateSpotSettlement(FinanceSettlement financeSettlement, BigDecimal balance) {
        Finance finance = financeMapper.selectOne(new QueryWrapper<Finance>().lambda().eq(Finance::getOrderId, financeSettlement.getOrderId()));
        if (finance != null) {
            if (financeSettlement.getType() == 1) {
                finance.setSpotHas(finance.getSpotHas().add(balance));
                finance.setSpotUn(finance.getSpotUn().subtract(balance));
                financeMapper.updateById(finance);
            } else if (financeSettlement.getType() == 2) {
                finance.setDeliveryHas(finance.getDeliveryHas().add(balance));
                finance.setDeliveryUn(finance.getDeliveryUn().subtract(balance));
                financeMapper.updateById(finance);
            } else if (financeSettlement.getType() == 3) {
                finance.setBackHas(finance.getBackHas().add(balance));
                finance.setBackUn(finance.getBackUn().subtract(balance));
                financeMapper.updateById(finance);
            } else if (financeSettlement.getType() == 4) {
                finance.setSlotHas(finance.getSlotHas().add(balance));
                finance.setSlotUn(finance.getSlotUn().subtract(balance));
                financeMapper.updateById(finance);
            } else if (financeSettlement.getType() == 5) {
                finance.setKickbackHas(finance.getKickbackHas().add(balance));
                finance.setKickbackUn(finance.getKickbackUn().subtract(balance));
                financeMapper.updateById(finance);
            } else if (financeSettlement.getType() == 6) {
                finance.setPickHas(finance.getPickHas().add(balance));
                finance.setPickUn(finance.getPickUn().subtract(balance));
                financeMapper.updateById(finance);
            } else if (financeSettlement.getType() == 7) {
                finance.setTakeHas(finance.getTakeHas().add(balance));
                finance.setTakeUn(finance.getTakeUn().subtract(balance));
                financeMapper.updateById(finance);
            }
        }
        // 财务明细
        dealUpdateFinanceDetail(financeSettlement, balance);
    }

    private void dealUpdateFinanceDetail(FinanceSettlement financeSettlement, BigDecimal balance) {
        FinanceDetail fd = financeDetailMapper.getByOrderIdAndType(financeSettlement.getOrderId(), financeSettlement.getType());
        if (fd != null) {
            fd.setHasSettlement(fd.getHasSettlement().add(balance));
            fd.setUnSettlement(fd.getUnSettlement().subtract(balance));
            if (fd.getUnSettlement().compareTo(BigDecimal.ZERO) == 0) {
                fd.setStatus(2);
            } else if (fd.getUnSettlement().compareTo(fd.getNeedSettlement()) < 0) {
                fd.setStatus(1);
            } else if (fd.getUnSettlement().compareTo(fd.getNeedSettlement()) == 0) {
                fd.setStatus(0);
            } else {
                fd.setStatus(1);
            }
            financeDetailMapper.updateById(fd);
        }
    }

    @Override
    public void repealFinanceCheck(Long checkId, List<Long> ids) {
        // 对账单结算记录作废
        List<FinanceCheckDetail> list = financeCheckDetailMapper.selectList(new QueryWrapper<FinanceCheckDetail>().lambda().eq(FinanceCheckDetail::getFinanceCheckId, checkId).in(FinanceCheckDetail::getOrderId, ids));
        Long id = list.get(0).getFinanceCheckId();
        for (FinanceCheckDetail fcd : list) {
            FinanceDetail fd = financeDetailMapper.selectById(fcd.getFinanceDetailId());
            BigDecimal balance = BigDecimal.ZERO.subtract(fcd.getCheckFee().abs());
            switch (fd.getType()) {
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    FinanceSettlement fs = financeSettlementMapper.getByOrderIdAndTypeAndCheckId(fd.getOrderId(), fd.getType(), fcd.getFinanceCheckId());
                    if (fs != null) {
                        updateSpotSettlement(fs, balance);
                        // 结算记录作废
                        financeSettlementMapper.updateStatusById(fs.getId(), 1);
                    }
                    break;
                case 8:
                    FinanceSettlement fs1 = financeSettlementMapper.getByOrderIdAndTransportId(fd.getOrderId(), fd.getRelationId(), id);
                    if (fs1 != null) {
                        updateTransportSettlement(fs1, balance);
                        // 结算记录作废
                        financeSettlementMapper.updateStatusById(fs1.getId(), 1);
                    }
                    break;
                case 9:
                    FinanceSettlement fs2 = financeSettlementMapper.getByOrderIdAndOrderExtraFeeId(fd.getOrderId(), fd.getRelationId(), id);
                    if (fs2 != null) {
                        updateOtherSettlement(fs2, balance);
                        // 结算记录作废
                        financeSettlementMapper.updateStatusById(fs2.getId(), 1);
                    }
                    break;
            }
            // 结算状态变更
            changeFinanceStatus(fd.getOrderId());
            //财务明细表的结算记录改为未结算
            //fd.setStatus(0);
            //financeDetailMapper.updateById(fd);
            financeCheckDetailMapper.delete(new QueryWrapper<FinanceCheckDetail>().lambda().eq(FinanceCheckDetail::getId, fcd.getId()));
        }

        //如果当前  对账单结算记录表的数据都撤销了,就把financeCheck的记录改成作废
        Integer count = financeCheckDetailMapper.selectCount(new QueryWrapper<FinanceCheckDetail>().lambda().eq(FinanceCheckDetail::getFinanceCheckId, id));
        if (count == 0) {
            financeCheckMapper.updateStatusById(id, YesOrNoEnum.YES.type);
        }
    }

    @Override
    public boolean checkRepealFinanceSettlement(Long id, StringBuilder errorMsg) {
        FinanceSettlement fs = financeSettlementMapper.selectById(id);
        if (fs == null) {
            errorMsg.append("参数错误");
            return false;
        }
        // 结算状态是否可撤销
        if (fs.getStatus() != 0) {
            errorMsg.append("当前状态不可撤销");
            return false;
        }
        // 结算类型是否为手动结算，否则不可撤销
        if (fs.getOrigin() != 0) {
            errorMsg.append(fs.getOrigin() == 1 ? "【对账单结算】" : "【线上收款】" + "类型不可撤销");
            return false;
        }
        return true;
    }


    @Override
    public void repealFinanceSettlement(Long id) {
        FinanceSettlement fs = financeSettlementMapper.selectById(id);
        BigDecimal balance = BigDecimal.ZERO.subtract(fs.getSettlementFee().abs());
        // 结算记录作废
        financeSettlementMapper.updateStatusById(id, YesOrNoEnum.YES.type);
        switch (fs.getType()) {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
                updateSpotSettlement(fs, balance);
                break;
            case 8:
                updateTransportSettlement(fs, balance);
                break;
            case 9:
                updateOtherSettlement(fs, balance);
                break;
        }
        // 结算状态变更
        changeFinanceStatus(fs.getOrderId());
    }

    @Override
    public void exportCollectionExcel(FinanceDTO financeDTO, HttpServletResponse response) {
        // 数据组织
        Page<PkgFinanceCollection> list = financeMapper.getCollectionList(PageFactory.defaultPage(1, 9999), financeDTO, businessUtil.getTenantId());
        if (list != null && list.getRecords().size() > 0) {
            List<PkgFinanceCollectionExport> listExport = new ArrayList<>();
            for (PkgFinanceCollection financeCollection : list.getRecords()) {
                financeCollection.setStartCode(cmCityMapper.getNameByCode(financeCollection.getStartCode()));
                financeCollection.setDestinationCode(cmCityMapper.getNameByCode(financeCollection.getDestinationCode()));
                PkgFinanceCollectionExport export = new PkgFinanceCollectionExport();
                BeanUtils.copyProperties(financeCollection, export);
                export.setCreateTime(DateUtil.format(financeCollection.getCreateTime(), "yyyy-MM-dd HH:mm"));
                listExport.add(export);
            }
            String fileName = (financeDTO.getCollectionStatus() == 0 ? "未" : "已") + "收账单"
                    + DateUtil.format(new Date(), "yyyy-MM-dd");
            List<ExcelHeaderInfo> headerInfos = Arrays.asList(
                    new ExcelHeaderInfo(0, 1, 0, 26, fileName));
            ExcelUtils excelUtils = new ExcelUtils(listExport, getCollectionHeadInfo(), headerInfos, getFormatInfo());
            excelUtils.sendHttpResponse(response, fileName, excelUtils.getWorkbook());
        }
    }

    @Override
    public void exportPaymentExcel(FinanceDTO financeDTO, HttpServletResponse response) {
        // 数据组织
        Page<PkgFinancePayment> list = financeMapper.getPaymentList(PageFactory.defaultPage(1, 9999), financeDTO, businessUtil.getTenantId());
        if (list != null && list.getRecords().size() > 0) {
            List<PkgFinancePaymentExport> listExport = new ArrayList<>();
            for (PkgFinancePayment financePayment : list.getRecords()) {
                financePayment.setStartCode(cmCityMapper.getNameByCode(financePayment.getStartCode()));
                financePayment.setDestinationCode(cmCityMapper.getNameByCode(financePayment.getDestinationCode()));
                PkgFinancePaymentExport export = new PkgFinancePaymentExport();
                BeanUtils.copyProperties(financePayment, export);
                export.setCreateTime(DateUtil.format(financePayment.getCreateTime(), "yyyy-MM-dd HH:mm"));
                listExport.add(export);
            }
            String fileName = (financeDTO.getPaymentStatus() == 0 ? "未" : "已") + "付账单"
                    + DateUtil.format(new Date(), "yyyy-MM-dd");
            List<ExcelHeaderInfo> headerInfos = Arrays.asList(
                    new ExcelHeaderInfo(0, 1, 0, 36, fileName));
            ExcelUtils excelUtils = new ExcelUtils(listExport, getPaymentHeadInfo(), headerInfos, getFormatInfo());
            excelUtils.sendHttpResponse(response, fileName, excelUtils.getWorkbook());
        }
    }

    @Override
    public void exportGross(FinanceDTO financeDTO, HttpServletResponse response) {

        Page<PkgFinanceGross> list = financeMapper.getFinanceGrossList(PageFactory.defaultPage(1, 9999), financeDTO, businessUtil.getTenantId());
        if (list != null && list.getRecords().size() > 0) {
            List<PkgFinanceGrossExport> listExport = new ArrayList<>();
            for (PkgFinanceGross financeGross : list.getRecords()) {
                financeGross.setStartCode(cmCityMapper.getNameByCode(financeGross.getStartCode()));
                financeGross.setDestinationCode(cmCityMapper.getNameByCode(financeGross.getDestinationCode()));
                PkgFinanceGrossExport export = new PkgFinanceGrossExport();
                BeanUtils.copyProperties(financeGross, export);

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                export.setCreateTime(sdf.format(financeGross.getCreateTime()));
                listExport.add(export);
            }
            String fileName = "毛利表"
                    + DateUtil.format(new Date(), "yyyy-MM-dd");
            List<ExcelHeaderInfo> headerInfos = Arrays.asList(
                    new ExcelHeaderInfo(0, 1, 0, 19, fileName));
            ExcelUtils excelUtils = new ExcelUtils(listExport, getGrossHeadInfo(), headerInfos, getFormatInfo());
            excelUtils.sendHttpResponse(response, fileName, excelUtils.getWorkbook());
        }
    }

    private List<ExcelHeaderInfo> getGrossHeadInfo() {
        return Arrays.asList(
                new ExcelHeaderInfo(2, 2, 0, 0, "子订单号"),
                new ExcelHeaderInfo(2, 2, 1, 1, "订单状态"),
                new ExcelHeaderInfo(2, 2, 2, 2, "制单人"),
                new ExcelHeaderInfo(2, 2, 3, 3, "制单时间"),
                new ExcelHeaderInfo(2, 2, 4, 4, "客户"),
                new ExcelHeaderInfo(2, 2, 5, 5, "联系方式"),
                new ExcelHeaderInfo(2, 2, 6, 6, "收货人"),
                new ExcelHeaderInfo(2, 2, 7, 7, "联系方式"),
                new ExcelHeaderInfo(2, 2, 8, 8, "出发地"),
                new ExcelHeaderInfo(2, 2, 9, 9, "目的地"),
                new ExcelHeaderInfo(2, 2, 10, 10, "车型"),
                new ExcelHeaderInfo(2, 2, 11, 11, "车架号"),
                new ExcelHeaderInfo(2, 2, 12, 12, "总运费"),
                new ExcelHeaderInfo(2, 2, 13, 13, "商务费"),
                new ExcelHeaderInfo(2, 2, 14, 14, "提车费"),
                new ExcelHeaderInfo(2, 2, 15, 15, "承运费"),
                new ExcelHeaderInfo(2, 2, 16, 16, "送车费"),
                new ExcelHeaderInfo(2, 2, 17, 17, "其他费用"),
                new ExcelHeaderInfo(2, 2, 18, 18, "税额"),
                new ExcelHeaderInfo(2, 2, 19, 19, "费用合计"),
                new ExcelHeaderInfo(2, 2, 20, 20, "毛利"),
                new ExcelHeaderInfo(2, 2, 21, 21, "订单备注"),
                new ExcelHeaderInfo(2, 2, 22, 22, "运输方式")
        );
    }


    /**
     * 获取订单财务信息表
     *
     * @author yujie
     * @since 2023/05/09 17:17
     */
    private Finance queryFinance(FinanceParam financeParam) {
        Finance finance = this.getById(financeParam.getId());
        if (ObjectUtil.isEmpty(finance)) {
            throw new ServiceException(FinanceExceptionEnum.NOT_EXISTED);
        }
        return finance;
    }


    public OrderExtraFee getExtraFeeDetail(String id) {
        return orderExtraFeeMapper.selectById(id);
    }

    public boolean checkOrderExtraFeeAdd(OrderExtraFee orderExtraFee, StringBuilder errorMsg) {
        if (orderExtraFee == null || orderExtraFee.getOrderId() == null) {
            errorMsg.append("参数错误，订单ID不可为空");
            return false;
        }
        if (orderExtraFee.getSettlementId() == null) {
            errorMsg.append("结算人ID不能为空");
            return false;
        }
        if (orderExtraFee.getFee() == null) {
            errorMsg.append("结算人金额不能为空");
            return false;
        }
        CmLinkman linkman = linkmanMapper.selectById(orderExtraFee.getSettlementId());
        if (linkman != null) {
            orderExtraFee.setSettlementName(linkman.getName());
        }
        return true;
    }

    @Transactional
    public void addOrderExtraFee(OrderExtraFee oef) {
        oef.setUnSettlement(oef.getFee());
        oef.setHasSettlement(BigDecimal.ZERO);
        orderExtraFeeMapper.insert(oef);
        // 财务明细表增加
        FinanceDetail fd = new FinanceDetail();
        fd.setNeedSettlement(oef.getFee());
        fd.setHasSettlement(BigDecimal.ZERO);
        fd.setUnSettlement(oef.getFee());
        fd.setSettlementUserId(oef.getSettlementId());
        fd.setSettlementUser(oef.getSettlementName());
        fd.setSettlementPhone(oef.getSettlementPhone());
        fd.setType(FinanceTypeEnum.OTHER.type);
        fd.setRelationId(oef.getId());
        fd.setOrderId(oef.getOrderId());
        financeDetailMapper.insert(fd);
    }

    public boolean checkOrderExtraFeeUpdate(OrderExtraFee orderExtraFee, StringBuilder errorMsg) {
        if (orderExtraFee == null || orderExtraFee.getId() == null) {
            errorMsg.append("参数错误！");
            return false;
        }
        if (orderExtraFee.getSettlementId() == null) {
            errorMsg.append("结算人ID不能为空");
            return false;
        }
        if (orderExtraFee.getFee() == null) {
            errorMsg.append("结算金额不能为空");
            return false;
        }
        OrderExtraFee origin = orderExtraFeeMapper.selectById(orderExtraFee.getId());
        orderExtraFee.setOrderId(origin.getOrderId());
        FinanceDetail fd = financeDetailMapper.selectOne(new QueryWrapper<FinanceDetail>().lambda()
                .eq(FinanceDetail::getRelationId, orderExtraFee.getId()));
        if (orderExtraFee.getFee().compareTo(fd.getHasSettlement()) < 0) {
            errorMsg.append("已经结算的费用不可修改");
            return false;
        }
        CmLinkman linkman = linkmanMapper.selectById(orderExtraFee.getSettlementId());
        if (linkman != null) {
            orderExtraFee.setSettlementName(linkman.getName());
        }
        return true;
    }

    @Transactional
    public void updateOrderExtraFee(OrderExtraFee orderExtraFee) {
        OrderExtraFee origin = orderExtraFeeMapper.selectById(orderExtraFee.getId());
        FinanceDetail fd = financeDetailMapper.selectOne(new QueryWrapper<FinanceDetail>().lambda()
                .eq(FinanceDetail::getRelationId, origin.getId()));
        // 订单修改明细
        List<OrderModifyDetail> list = new ArrayList<>();
        Long orderId = origin.getOrderId();
        Long userId = LoginContextHolder.me().getSysLoginUserId();
        // 费用类型
        if (BaseUtils.neCompareTwo(origin.getType(), orderExtraFee.getType())) {
            list.add(new OrderModifyDetail(orderId, origin.getTransportId(), "type", "费用类型", orderExtraFee.getType().toString(), origin.getType().toString(), userId));
        }
        // 结算人
        if (BaseUtils.neCompareTwo(origin.getSettlementName(), orderExtraFee.getSettlementName())) {
            list.add(new OrderModifyDetail(orderId, origin.getTransportId(), "settlement_name", "结算人", orderExtraFee.getSettlementName(), origin.getSettlementName(), userId));
        }
        // 结算人电话
        if (BaseUtils.neCompareTwo(origin.getSettlementPhone(), orderExtraFee.getSettlementPhone())) {
            list.add(new OrderModifyDetail(orderId, origin.getTransportId(), "settlement_phone", "结算人电话", orderExtraFee.getSettlementPhone(), origin.getSettlementPhone(), userId));
        }
        // 如果修改了结算人，需要修改财务表
        if (BaseUtils.neCompareTwo(orderExtraFee.getSettlementId(), origin.getSettlementId())) {
            financeDetailMapper.updateSettlementUserInfoByRelationId(origin.getId(), orderExtraFee.getSettlementName(), orderExtraFee.getSettlementPhone(), orderExtraFee.getSettlementId());
        }
        // 金额
        if (!BaseUtils.compareDecimal(origin.getFee(), orderExtraFee.getFee())) {
            // 修改金额
            try {
                if (fd != null) {
                    if (fd.getHasSettlement().compareTo(BigDecimal.ZERO) > 0 && orderExtraFee.getFee().compareTo(fd.getHasSettlement()) < 0) {
                        // 不可改为小于已经结算的金额
                        throw new CustomException("不可改为小于已经结算的金额");
                    }
                    fd.setNeedSettlement(orderExtraFee.getFee());
                    fd.setUnSettlement(orderExtraFee.getFee().subtract(fd.getHasSettlement()));
                    if (fd.getUnSettlement().compareTo(BigDecimal.ZERO) == 0) {
                        fd.setStatus(2);
                    } else {
                        fd.setStatus(0);
                    }
                    financeDetailMapper.updateById(fd);
                }
            } catch (Exception e) {
                throw new CustomException(e.getMessage());
            }
            assert fd != null;
            orderExtraFee.setUnSettlement(orderExtraFee.getFee().subtract(fd.getHasSettlement()));
            orderExtraFeeMapper.updateById(orderExtraFee);
            list.add(new OrderModifyDetail(orderId, origin.getTransportId(), "fee", "金额", orderExtraFee.getFee().toString(), origin.getFee().toString(), userId));
        }
        if (list.size() > 0) {
            for (OrderModifyDetail orderModifyDetail : list) {
                orderModifyDetailMapper.insert(orderModifyDetail);
            }
        }
    }

    public boolean checkOrderExtraFeeDelete(String id, StringBuilder errorMsg) {
        OrderExtraFee oef = orderExtraFeeMapper.selectById(id);
        if (oef.getHasSettlement() != null && oef.getHasSettlement().compareTo(BigDecimal.ZERO) > 0) {
            errorMsg.append("已经结算的费用不可删除");
            return false;
        }
        return true;
    }

    @Transactional
    public void deleteOrderExtraFee(String id) {
        orderExtraFeeMapper.deleteById(id);
        financeDetailMapper.deleteByRelationId(id);
    }

    public List<OrderExtraFee> getExtraFeeListByOrderId(String orderId) {
        return orderExtraFeeMapper.selectList(new QueryWrapper<OrderExtraFee>().lambda().eq(OrderExtraFee::getOrderId, orderId));
    }


}